[PATCH] D98686: [lld:elf] Weaken the requirement for a computed binding to be STB_LOCAL
Fangrui Song via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Wed Mar 17 18:56:57 PDT 2021
MaskRay added a comment.
I'd completely rewrite the description. Consider this:
// Cat.cpp
struct Animal { virtual void makeNoise() const = 0; };
struct Cat : Animal { void makeNoise() const override; };
extern "C" int puts(char const *);
void Cat::makeNoise() const { puts("Meow"); }
void doThingWithCat(Animal *a) { static_cast<Cat *>(a)->makeNoise(); }
// CatUser.cpp
struct Animal { virtual void makeNoise() const = 0; };
struct Cat : Animal { void makeNoise() const override; };
void doThingWithCat(Animal *a);
void useDoThingWithCat() {
Cat *d = new Cat;
doThingWithCat(d);
}
// cat.ver
{
global: _Z17useDoThingWithCatv;
local: *;
};
clang++ Cat.cpp CatUser.cpp -fpic -flto=thin -fwhole-program-vtables -shared -O3 -fuse-ld=lld -Wl,--lto-whole-program-visibility -Wl,--version-script,cat.ver
We cannot devirtualize `makeNoise`. The issue is complex:
1. Due to `-fsplit-lto-unit` and usage of type metadata, we place the Cat vtable declaration into module 0 and the Cat vtable definition with type metadata into module 1, causing duplicate entries (Undefined followed by Defined) in the `lto::InputFile::symbols()` output.
2. In `BitcodeFile::parse`, after processing the Undefined then the Defined, the final state is Defined.
3. In `BitcodeCompiler::add`, for the first symbol, `computeBinding` returns STB_LOCAL, then we reset it to Undefined because it is prevailing (`versionId` is preserved). For the second symbol, because the state is now Undefined, `computeBinding` returns TB_GLOBAL, causing `ExportDynamic` to be true and suppressing devirtualization.
In D77280 <https://reviews.llvm.org/D77280>, the `computeBinding` change used a stricter `isDefined()` condition to make weak Lazy symbol work.
This patch relaxes the condition to weaker `!isLazy()` to keep it working while making the devirtualization work as well.
================
Comment at: lld/test/ELF/lto/devirt_extern_vtable.ll:6
+;; Hybrid WPD
+; RUN: opt --thinlto-bc --thinlto-split-lto-unit -o %t1.o %s
+; RUN: opt --thinlto-bc --thinlto-split-lto-unit %S/Inputs/devirt_extern_vtable.ll -o %t2.o
----------------
You can use `split-file` to place auxiliary files in one file. See some newer tests for example.
================
Comment at: lld/test/ELF/lto/devirt_extern_vtable.ll:11
+; RUN: ld.lld %t1.o %t2.o -shared -o %t3 -save-temps --lto-whole-program-visibility \
+; RUN: -mllvm -pass-remarks=. --version-script %t.ver 2>&1 \
+; RUN: | FileCheck %s --check-prefix=REMARK
----------------
nit: ` | \` (the previous line instead of the continuation line)
================
Comment at: lld/test/ELF/lto/devirt_extern_vtable.ll:54
+ store %struct.Animal* %a, %struct.Animal** %a.addr, align 8
+ %0 = load %struct.Animal*, %struct.Animal** %a.addr, align 8
+ %1 = bitcast %struct.Animal* %0 to %struct.Cat*
----------------
Can you compile with higher optimization and remove unneeded instructions?
================
Comment at: lld/test/ELF/lto/devirt_extern_vtable.ll:84
+attributes #0 = { noinline optnone uwtable mustprogress "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
+attributes #1 = { "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
+attributes #2 = { nofree nosync nounwind readnone willreturn }
----------------
Attributes need clean-up.
================
Comment at: lld/test/ELF/lto/devirt_extern_vtable.ll:89
+!llvm.linker.options = !{}
+!llvm.module.flags = !{!4, !5}
+
----------------
Delete unneeded module flags and !llvm.linker.options.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D98686/new/
https://reviews.llvm.org/D98686
More information about the llvm-commits
mailing list