mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
The change replaces 'set bit enumeration' with arithmetic and bitwise operations. For example, the formula '(((x & -x) + x) & x) ^ x' can be used to find the rightmost contiguous bit mask. This is essentially the operation that SetBitEnumerator.findNext() performed. Removing this functionality reduces the complexity of the ClusteredBitVector (a.k.a. SpareBitVector) implementation and, more importantly, API which will make it easier to modify the implementation of spare bit masks going forward. My end goal being to make spare bit operations work more reliably on big endian systems. Side note: This change modifies the emit gather/scatter functions so that they work with an APInt, rather than a SpareBitVector, which makes these functions a bit more generic. These functions emit instructions that are essentially equivalent to the parallel bit extract/deposit (PEXT and PDEP) instructions in BMI2 on x86_64 (although we don't emit those directly currently). They also map well to bitwise manipulation instructions on other platforms (e.g. RISBG on IBM Z). So we might find uses for them outside spare bit manipulation in the future.
186 lines
5.3 KiB
C++
186 lines
5.3 KiB
C++
#include "swift/Basic/ClusteredBitVector.h"
|
|
#include "llvm/Support/Format.h"
|
|
#include "llvm/Support/raw_ostream.h"
|
|
#include "llvm/ADT/Twine.h"
|
|
#include <vector>
|
|
#include "stdlib.h"
|
|
|
|
using namespace swift;
|
|
|
|
const unsigned NV = 16;
|
|
|
|
/// Random number in [0,n)
|
|
unsigned randCount(unsigned n) {
|
|
return unsigned(rand()) % n;
|
|
}
|
|
unsigned randNV() { return randCount(NV); }
|
|
|
|
static void checkConsistency(const Twine &name, const ClusteredBitVector &cbv,
|
|
const std::vector<bool> &vec, unsigned depth) {
|
|
auto finish = [=]() {
|
|
for (unsigned j = depth; j != 0; --j) {
|
|
llvm::outs().indent(2 * (j-1)) << "}\n";
|
|
}
|
|
abort();
|
|
};
|
|
|
|
auto n = cbv.size();
|
|
if (n != vec.size()) {
|
|
llvm::outs().indent(2 * depth)
|
|
<< "assert(" << name << ".size() == " << vec.size() << ");\n";
|
|
finish();
|
|
}
|
|
|
|
for (auto i = 0; i != n; ++i) {
|
|
if (cbv[i] != vec[i]) {
|
|
llvm::outs().indent(2 * depth)
|
|
<< "assert(" << name << "[" << i << "] == "
|
|
<< (vec[i] ? "true" : "false") << ");\n";
|
|
finish();
|
|
}
|
|
}
|
|
}
|
|
|
|
static void run() {
|
|
llvm::outs() << "#include \"swift/Basic/ClusteredBitVector.h\"\n";
|
|
llvm::outs() << "using namespace swift;\n";
|
|
llvm::outs() << "int main() {\n";
|
|
llvm::outs() << " ClusteredBitVector cbvs[" << NV << "];\n";
|
|
ClusteredBitVector cbvs[NV];
|
|
std::vector<bool> vecs[NV];
|
|
|
|
unsigned nextTemp = 0;
|
|
|
|
while (true) {
|
|
switch (randCount(10)) {
|
|
case 0: {
|
|
auto from = randNV();
|
|
auto to = randNV();
|
|
if (from == to) continue;
|
|
llvm::outs() << " cbvs[" << to << "].append(cbvs[" << from << "]);\n";
|
|
cbvs[to].append(cbvs[from]);
|
|
vecs[to].insert(vecs[to].end(), vecs[from].begin(), vecs[from].end());
|
|
break;
|
|
}
|
|
|
|
case 1: {
|
|
auto from = randNV();
|
|
auto to = randNV();
|
|
if (from == to) continue;
|
|
llvm::outs() << " cbvs[" << to << "] = cbvs[" << from << "];\n";
|
|
cbvs[to] = cbvs[from];
|
|
vecs[to] = vecs[from];
|
|
break;
|
|
}
|
|
|
|
case 2: {
|
|
auto from = randNV();
|
|
auto to = randNV();
|
|
if (from == to) continue;
|
|
llvm::outs() << " cbvs[" << to << "] = std::move(cbvs[" << from << "]);\n";
|
|
cbvs[to] = std::move(cbvs[from]);
|
|
vecs[to] = std::move(vecs[from]);
|
|
break;
|
|
}
|
|
|
|
case 3: {
|
|
auto from = randNV();
|
|
auto to = randNV();
|
|
auto temp = nextTemp++;
|
|
llvm::outs() << " { ClusteredBitVector temp" << temp << " = cbvs[" << from << "];\n";
|
|
ClusteredBitVector tempCBV = cbvs[from];
|
|
auto tempVec = vecs[from];
|
|
checkConsistency("temp" + Twine(temp), tempCBV, tempVec, 2);
|
|
llvm::outs() << " cbvs[" << to << "] = temp" << temp << "; }\n";
|
|
cbvs[to] = tempCBV;
|
|
vecs[to] = tempVec;
|
|
break;
|
|
}
|
|
|
|
case 4: {
|
|
auto from = randNV();
|
|
auto to = randNV();
|
|
auto temp = nextTemp++;
|
|
llvm::outs() << " { ClusteredBitVector temp" << temp << " = std::move(cbvs[" << from << "]);\n";
|
|
ClusteredBitVector tempCBV = std::move(cbvs[from]);
|
|
auto tempVec = std::move(vecs[from]);
|
|
checkConsistency("temp" + Twine(temp), tempCBV, tempVec, 2);
|
|
llvm::outs() << " cbvs[" << to << "] = temp" << temp << "; }\n";
|
|
cbvs[to] = tempCBV;
|
|
vecs[to] = tempVec;
|
|
break;
|
|
}
|
|
|
|
case 5: {
|
|
auto from = randNV();
|
|
auto to = randNV();
|
|
auto temp = nextTemp++;
|
|
llvm::outs() << " { ClusteredBitVector temp" << temp << " = cbvs[" << from << "];\n";
|
|
ClusteredBitVector tempCBV = cbvs[from];
|
|
auto tempVec = vecs[from];
|
|
checkConsistency("temp" + Twine(temp), tempCBV, tempVec, 2);
|
|
llvm::outs() << " cbvs[" << to << "] = std::move(temp" << temp << "); }\n";
|
|
cbvs[to] = std::move(tempCBV);
|
|
vecs[to] = std::move(tempVec);
|
|
break;
|
|
}
|
|
|
|
case 6: {
|
|
auto from = randNV();
|
|
auto to = randNV();
|
|
auto temp = nextTemp++;
|
|
llvm::outs() << " { ClusteredBitVector temp" << temp << " = std::move(cbvs[" << from << "]);\n";
|
|
ClusteredBitVector tempCBV = std::move(cbvs[from]);
|
|
auto tempVec = std::move(vecs[from]);
|
|
checkConsistency("temp" + Twine(temp), tempCBV, tempVec, 2);
|
|
llvm::outs() << " cbvs[" << to << "] = std::move(temp" << temp << "); }\n";
|
|
cbvs[to] = std::move(tempCBV);
|
|
vecs[to] = std::move(tempVec);
|
|
break;
|
|
}
|
|
|
|
case 7: {
|
|
auto to = randNV();
|
|
auto count = randCount(32);
|
|
auto bits = randCount(1ULL << count);
|
|
llvm::outs() << " cbvs[" << to << "].add(" << count << ", "
|
|
<< llvm::format_hex(bits, 18) << ");\n";
|
|
cbvs[to].add(count, bits);
|
|
while (count--) {
|
|
vecs[to].push_back(bits & 1);
|
|
bits >>= 1;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case 8: {
|
|
auto to = randNV();
|
|
auto count = randCount(128);
|
|
llvm::outs() << " cbvs[" << to << "].appendClearBits(" << count << ");\n";
|
|
cbvs[to].appendClearBits(count);
|
|
while (count--) vecs[to].push_back(false);
|
|
break;
|
|
}
|
|
|
|
case 9: {
|
|
auto to = randNV();
|
|
auto count = randCount(128);
|
|
llvm::outs() << " cbvs[" << to << "].appendSetBits(" << count << ");\n";
|
|
cbvs[to].appendSetBits(count);
|
|
while (count--) vecs[to].push_back(true);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Validate that everything's still okay.
|
|
for (auto i = 0; i != NV; ++i) {
|
|
checkConsistency("cbvs[" + Twine(i) + "]", cbvs[i], vecs[i], 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
int main() {
|
|
sranddev();
|
|
run();
|
|
}
|