mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 02:33:06 +01:00
Introduce a generic operator to apply complex operations to BitVector
This avoids temporary and memcpy call when computing large expressions. It's basically some kind of poor man's expression template, but it seems easier to maintain to have a single generic `apply` call instead of the whole expression template machinery here. Differential Revision: https://reviews.llvm.org/D98176
This commit is contained in:
parent
dbfefbf5ff
commit
1ea67d638f
@ -568,6 +568,20 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class F, class... ArgTys>
|
||||
static BitVector &apply(F &&f, BitVector &Out, BitVector const &Arg,
|
||||
ArgTys const &...Args) {
|
||||
assert(llvm::all_of(
|
||||
std::initializer_list<unsigned>{Args.size()...},
|
||||
[&Arg](auto const &BV) { return Arg.size() == BV; }) &&
|
||||
"consistent sizes");
|
||||
Out.resize(Arg.size());
|
||||
for (size_t i = 0, e = Out.NumBitWords(Arg.size()); i != e; ++i)
|
||||
Out.Bits[i] = f(Arg.Bits[i], Args.Bits[i]...);
|
||||
Out.clear_unused_bits();
|
||||
return Out;
|
||||
}
|
||||
|
||||
BitVector &operator|=(const BitVector &RHS) {
|
||||
if (size() < RHS.size())
|
||||
resize(RHS.size());
|
||||
|
@ -264,9 +264,9 @@ void CFIInstrInserter::calculateOutgoingCFAInfo(MBBCFAInfo &MBBInfo) {
|
||||
MBBInfo.OutgoingCFARegister = SetRegister;
|
||||
|
||||
// Update outgoing CSR info.
|
||||
MBBInfo.OutgoingCSRSaved = MBBInfo.IncomingCSRSaved;
|
||||
MBBInfo.OutgoingCSRSaved |= CSRSaved;
|
||||
MBBInfo.OutgoingCSRSaved.reset(CSRRestored);
|
||||
BitVector::apply([](auto x, auto y, auto z) { return (x | y) & ~z; },
|
||||
MBBInfo.OutgoingCSRSaved, MBBInfo.IncomingCSRSaved, CSRSaved,
|
||||
CSRRestored);
|
||||
}
|
||||
|
||||
void CFIInstrInserter::updateSuccCFAInfo(MBBCFAInfo &MBBInfo) {
|
||||
@ -294,6 +294,7 @@ bool CFIInstrInserter::insertCFIInstrs(MachineFunction &MF) {
|
||||
const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
|
||||
bool InsertedCFIInstr = false;
|
||||
|
||||
BitVector SetDifference;
|
||||
for (MachineBasicBlock &MBB : MF) {
|
||||
// Skip the first MBB in a function
|
||||
if (MBB.getNumber() == MF.front().getNumber()) continue;
|
||||
@ -345,8 +346,8 @@ bool CFIInstrInserter::insertCFIInstrs(MachineFunction &MF) {
|
||||
continue;
|
||||
}
|
||||
|
||||
BitVector SetDifference = PrevMBBInfo->OutgoingCSRSaved;
|
||||
SetDifference.reset(MBBInfo.IncomingCSRSaved);
|
||||
BitVector::apply([](auto x, auto y) { return x & ~y; }, SetDifference,
|
||||
PrevMBBInfo->OutgoingCSRSaved, MBBInfo.IncomingCSRSaved);
|
||||
for (int Reg : SetDifference.set_bits()) {
|
||||
unsigned CFIIndex =
|
||||
MF.addFrameInst(MCCFIInstruction::createRestore(nullptr, Reg));
|
||||
@ -355,8 +356,8 @@ bool CFIInstrInserter::insertCFIInstrs(MachineFunction &MF) {
|
||||
InsertedCFIInstr = true;
|
||||
}
|
||||
|
||||
SetDifference = MBBInfo.IncomingCSRSaved;
|
||||
SetDifference.reset(PrevMBBInfo->OutgoingCSRSaved);
|
||||
BitVector::apply([](auto x, auto y) { return x & ~y; }, SetDifference,
|
||||
MBBInfo.IncomingCSRSaved, PrevMBBInfo->OutgoingCSRSaved);
|
||||
for (int Reg : SetDifference.set_bits()) {
|
||||
auto it = CSRLocMap.find(Reg);
|
||||
assert(it != CSRLocMap.end() && "Reg should have an entry in CSRLocMap");
|
||||
|
@ -779,6 +779,7 @@ TYPED_TEST(BitVectorTest, ProxyIndex) {
|
||||
EXPECT_TRUE(Vec.none());
|
||||
}
|
||||
|
||||
|
||||
TYPED_TEST(BitVectorTest, PortableBitMask) {
|
||||
TypeParam A;
|
||||
const uint32_t Mask1[] = { 0x80000000, 6, 5 };
|
||||
@ -1261,4 +1262,40 @@ TYPED_TEST(BitVectorTest, DenseMapHashing) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST(BitVectoryTest, Apply) {
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
int j = i * 100 + 3;
|
||||
|
||||
const BitVector x =
|
||||
createBitVector<BitVector>(j + 5, {{i, i + 1}, {j - 1, j}});
|
||||
const BitVector y = createBitVector<BitVector>(j + 5, {{i, j}});
|
||||
const BitVector z =
|
||||
createBitVector<BitVector>(j + 5, {{i + 1, i + 2}, {j, j + 1}});
|
||||
|
||||
auto op0 = [](auto x) { return ~x; };
|
||||
BitVector expected0 = x;
|
||||
expected0.flip();
|
||||
BitVector out0(j - 2);
|
||||
BitVector::apply(op0, out0, x);
|
||||
EXPECT_EQ(out0, expected0);
|
||||
|
||||
auto op1 = [](auto x, auto y) { return x & ~y; };
|
||||
BitVector expected1 = x;
|
||||
expected1.reset(y);
|
||||
BitVector out1;
|
||||
BitVector::apply(op1, out1, x, y);
|
||||
EXPECT_EQ(out1, expected1);
|
||||
|
||||
auto op2 = [](auto x, auto y, auto z) { return (x ^ ~y) | z; };
|
||||
BitVector expected2 = y;
|
||||
expected2.flip();
|
||||
expected2 ^= x;
|
||||
expected2 |= z;
|
||||
BitVector out2(j + 5);
|
||||
BitVector::apply(op2, out2, x, y, z);
|
||||
EXPECT_EQ(out2, expected2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
|
Loading…
Reference in New Issue
Block a user