Skip to content

Commit 4c17f9b

Browse files
authored
[BOLT] Make safe ICF work with relative vtable (#170629)
To support relative vtable, we divide each vtable entry address by 4 instead of 8 when tracking addresses covered by vtable using bitvector. This guarantees accuracy, saves the trouble of checking for each vtable whether it is relative, and is also necessary for libraries for which some contributing compilation units are compiled with relative vtable while others are not.
1 parent 09b0885 commit 4c17f9b

File tree

3 files changed

+32
-3
lines changed

3 files changed

+32
-3
lines changed

bolt/include/bolt/Passes/IdenticalCodeFolding.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,17 +37,19 @@ class IdenticalCodeFolding : public BinaryFunctionPass {
3737
Error runOnFunctions(BinaryContext &BC) override;
3838

3939
private:
40+
static constexpr uint64_t VTableAddressGranularity = 4;
41+
4042
/// Bit vector of memory addresses of vtables.
4143
llvm::SparseBitVector<> VTableBitVector;
4244

4345
/// Return true if the memory address is in a vtable.
4446
bool isAddressInVTable(uint64_t Address) const {
45-
return VTableBitVector.test(Address / 8);
47+
return VTableBitVector.test(Address / VTableAddressGranularity);
4648
}
4749

4850
/// Mark memory address of a vtable as used.
4951
void setAddressUsedInVTable(uint64_t Address) {
50-
VTableBitVector.set(Address / 8);
52+
VTableBitVector.set(Address / VTableAddressGranularity);
5153
}
5254

5355
/// Scan symbol table and mark memory addresses of

bolt/lib/Passes/IdenticalCodeFolding.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,8 @@ void IdenticalCodeFolding::initVTableReferences(const BinaryContext &BC) {
380380
if (!Data->getName().starts_with("_ZTV") && // vtable
381381
!Data->getName().starts_with("_ZTCN")) // construction vtable
382382
continue;
383-
for (uint64_t I = Address, End = I + Data->getSize(); I < End; I += 8)
383+
for (uint64_t I = Address, End = I + Data->getSize(); I < End;
384+
I += VTableAddressGranularity)
384385
setAddressUsedInVTable(I);
385386
}
386387
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Test safe ICF works with binaries that contain relative vtable.
2+
3+
// REQUIRES: system-linux,asserts
4+
5+
// RUN: %clang %cxxflags -o %t.so %s -Wl,-q -fno-rtti
6+
// RUN: llvm-bolt %t.so -o %t.bolt --no-threads --icf=safe \
7+
// RUN: --debug-only=bolt-icf 2>&1 | FileCheck %s
8+
9+
// RUN: %clang %cxxflags -o %t.so %s -Wl,-q -fno-rtti \
10+
// RUN: -fexperimental-relative-c++-abi-vtables
11+
// RUN: llvm-bolt %t.so -o %t.bolt --no-threads --icf=safe \
12+
// RUN: --debug-only=bolt-icf 2>&1 | FileCheck %s
13+
14+
// CHECK: folding {{.*bar.*}} into {{.*foo.*}}
15+
// CHECK-NOT: skipping function with reference taken {{.*bar.*}}
16+
17+
class TT {
18+
public:
19+
virtual int foo(int a) { return ++a; }
20+
virtual int bar(int a) { return ++a; }
21+
};
22+
23+
int main() {
24+
TT T;
25+
return T.foo(0) + T.bar(1);
26+
}

0 commit comments

Comments
 (0)