| commit | d99033e4b4081bc47510c451b618ef93fe2f3c62 | [log] [tgz] |
|---|---|---|
| author | Mingming Liu <mingmingl@google.com> | Wed Mar 19 22:10:57 2025 -0700 |
| committer | GitHub <noreply@github.com> | Wed Mar 19 22:10:57 2025 -0700 |
| tree | 895787d8b778f8717ee54ecdbad60f97724a6758 | |
| parent | d0d33d2b5ba3369d4a5586234181055935965e49 [diff] |
[LTO][WPD] Suppress WPD on a class if the LTO unit doesn't have the prevailing definition of this class (#131721)
Before this patch, whole program devirtualization is suppressed on a
class if any superclass is visible to regular object files, by recording
the class GUID in `VisibleToRegularObjSymbols`.
This patch suppresses whole program devirtualization on a class if the
LTO unit doesn't have the prevailing definition of this class (e.g., the
prevailing definition is in a shared library)
Implementation summaries:
1. In llvm/lib/LTO/LTO.cpp, `IsVisibleToRegularObj` is updated to look
at the global resolution's `IsPrevailing` bit for ThinLTO and
regularLTO.
2. In llvm/tools/llvm-lto2/llvm-lto2.cpp,
- three command line options are added so `llvm-lto2` can override
`Conf.HasWholeProgramVisibility`, `Conf.ValidateAllVtablesHaveTypeInfos`
and `Conf.AllVtablesHaveTypeInfos`.
The test case is reduced from a small C++ program (main.cc, lib.cc/h
pasted below in [1]). To reproduce the program failure without this
patch, compile lib.cc into a shared library, and provide it to a ThinLTO
build of main.cc (commands are pasted in [2]).
[1]
* lib.h
```
#include <cstdio>
class Derived {
public:
void dispatch();
virtual void print();
virtual void sum();
};
void Derived::dispatch() {
static_cast<Derived*>(this)->print();
static_cast<Derived*>(this)->sum();
}
void Derived::sum() {
printf("Derived::sum\n");
}
__attribute__((noinline)) void* create(int i);
__attribute__((noinline)) void* getPtr(int i);
```
* lib.cc
```
#include "lib.h"
#include <cstdio>
#include <iostream>
class Derived2 : public Derived {
public:
void print() override {
printf("DerivedSharedLib\n");
}
void sum() override {
printf("DerivedSharedLib::sum\n");
}
};
void Derived::print() {
printf("Derived\n");
}
__attribute__((noinline)) void* create(int i) {
if (i & 1)
return new Derived2();
return new Derived();
}
```
* main.cc
```
cat main.cc
#include "lib.h"
class DerivedN : public Derived {
public:
};
__attribute__((noinline)) void* getPtr(int x) {
return new DerivedN();
}
int main() {
Derived*b = static_cast<Derived*>(create(201));
b->dispatch();
delete b;
Derived* a = static_cast<Derived*>(getPtr(202));
a->dispatch();
delete a;
return 0;
}
```
[2]
```
# compile lib.o in a shared library.
$ ./bin/clang++ -O2 -fPIC -c lib.cc -o lib.o
$ ./bin/clang++ -shared -o libdata.so lib.o
# Provide the shared library in `-ldata`
$ ./bin/clang++ -v -g -ldata --save-temps -fno-discard-value-names -Wl,-mllvm,-print-before=wholeprogramdevirt -Wl,-mllvm,-wholeprogramdevirt-check=trap -Rpass=wholeprogramdevirt -Wl,--lto-whole-program-visibility -Wl,--lto-validate-all-vtables-have-type-infos -mllvm -disable-icp=true -Wl,-mllvm,-disable-icp=false -flto=thin -fwhole-program-vtables -fno-split-lto-unit -fuse-ld=lld main.cc -L . -o main >/tmp/wholeprogramdevirt.ir 2>&1
# Run the program hits a segmentation fault with `-Wl,-mllvm,-wholeprogramdevirt-check=trap`
$ LD_LIBRARY_PATH=. ./main
DerivedSharedLib
Trace/breakpoint trap (core dumped)
```Welcome to the LLVM project!
This repository contains the source code for LLVM, a toolkit for the construction of highly optimized compilers, optimizers, and run-time environments.
The LLVM project has multiple components. The core of the project is itself called “LLVM”. This contains all of the tools, libraries, and header files needed to process intermediate representations and convert them into object files. Tools include an assembler, disassembler, bitcode analyzer, and bitcode optimizer.
C-like languages use the Clang frontend. This component compiles C, C++, Objective-C, and Objective-C++ code into LLVM bitcode -- and from there into object files, using LLVM.
Other components include: the libc++ C++ standard library, the LLD linker, and more.
Consult the Getting Started with LLVM page for information on building and running LLVM.
For information on how to contribute to the LLVM project, please take a look at the Contributing to LLVM guide.
Join the LLVM Discourse forums, Discord chat, LLVM Office Hours or Regular sync-ups.
The LLVM project has adopted a code of conduct for participants to all modes of communication within the project.