The gold-plugin was doing this internally, now the API is handling
commons correctly based on the given resolution.
I didn't test the gold plugin, I need someone to do it for me.
Differential D23739
[LTO] Handles commons in monolithic LTO mehdi_amini on Aug 19 2016, 9:29 PM. Authored by
Details The gold-plugin was doing this internally, now the API is handling I didn't test the gold plugin, I need someone to do it for me.
Diff Detail Event TimelineComment Actions I fixed a couple of unused variables, diff shown below. But I am getting a test failure, see further below. diff --git a/tools/gold/gold-plugin.cpp b/tools/gold/gold-plugin.cpp
+++ b/tools/gold/gold-plugin.cpp toString(ObjOrErr.takeError()).c_str()); InputFile &Obj = **ObjOrErr;
+ for (LLVM_ATTRIBUTE_UNUSED auto &ObjSym : Obj.symbols()) { ld_plugin_symbol &Sym = F.syms[SymNum]; SymbolResolution &R = Resols[SymNum]; ++SymNum; I am getting a failure in the gold common test: llvm_13/test/tools/gold/X86/common.ll:14:6: error: expected string not found in input ^ <stdin>:4:1: note: possible intended match here I'll need to dig unless you can figure out what might be going on. Will try to look tonight if I have time. Comment Actions Change the handling to ignore the prevailing information, every common are taken into account now. Comment Actions Still needs the unused var fixes I noted in the previous comments.
Comment Actions Getting a failure in your new test. I assume it wasn't designed for the case where we assume all are prevailing. /usr/local/google/home/tejohnson/llvm/llvm_13/test/tools/llvm-lto2/common.ll:61:23: error: expected string not found in input ^ <stdin>:1:1: note: scanning from here
Comment Actions This change doesn't look right to me. $ cat c1.c #include <stdio.h> short x; int main() { printf("%d\n", x); } $ cat c2.c int x = 42; $ src/llvm/ra/bin/clang -flto -fuse-ld=gold c1.c c2.c $ ./a.out 0 The previous implementation handled this correctly by tracking whether any common symbol prevailed. As I mentioned before, these semantics are gold-specific, and I don't want any other linker to rely on them. If nothing else, can we put these semantics behind a flag? Comment Actions I don't have an easy access to gold, can you provide the IR and the resolution so that I can reproduce with llvm-lto2? Ultimately we need a consistent story for commons, and document it clearly in the API. Comment Actions
Sure: $ cat c1.ll source_filename = "c1.c" target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" @x = common global i16 0, align 2 $ cat c2.ll ; ModuleID = 'c2.o' source_filename = "c2.c" target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" @x = global i32 42, align 4 $ ~/src/llvm/ra/bin/llvm-as -o c1.o c1.ll $ ~/src/llvm/ra/bin/llvm-as -o c2.o c2.ll $ ~/src/llvm/ra/bin/llvm-lto2 c1.o -r=c1.o,x,l c2.o -r=c2.o,x,pl -o foo -save-temps $ ~/src/llvm/ra/bin/llvm-dis -o - foo.0.0.preopt.bc ; ModuleID = 'foo.0.0.preopt.bc' source_filename = "ld-temp.o" target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" @x = common global [2 x i8] zeroinitializer, align 2
I think our story for all symbols should be that there can only be a maximum of a single prevailing symbol. That would be the simplest interface/implementation on the lib/LTO side. It is sufficient for non-ELF, and (with the exception of common symbols) for ELF. There are various workarounds that ELF linkers can use for common symbols, but the implementation of those workarounds ideally shouldn't live in lib/LTO. Comment Actions Thanks.
It means that we 1) rely on the client to pick the largest common and 2) we can't adjust the alignment to the largest So we need to make sure the IRMover handles correctly commons in this case and does not merge them but keep only the prevailing one. I wonder if we don't risk to have some issues though, if a module was generated with a larger alignement, the loads/stores can be annotated with the high alignment (and other optimization relies on that).
Can you clarify what makes it different for non-ELF linker to handle common? (Or what makes ELF linker to need workaround). Comment Actions
The logic already needs to exist in the linker anyway to handle native object files, so I don't see it as a huge problem.
I would ideally want to keep that logic out of lib/LTO (see below).
If we avoid emitting common symbols into the module, we can avoid this problem. I suspect optimizations involving alignment of common symbols to be rare, so maybe it's not worth the additional complexity to support them.
I was operating on the assumption that non-ELF linkers only take max size, which would make it straightforward to pick a single prevailing symbol, but from IRC it sounds like linkers for most object formats do in fact want something similar to max size + max alignment. The workaround I speak of is whatever is needed to create a symbol with the correct size and alignment. That can be done by synthesizing a common symbol that would be internal to the linker (i.e. not creating it in the module) and reporting all common symbols to lib/LTO as non-prevailing, or by creating a common symbol in the module and hence the native object file (which is what the code is currently doing). If clients can synthesize the symbol, we can avoid having to deal with this issue in lib/LTO. Creating the symbol in the native object file also seems like it may be more complicated on the linker side because it would need to be merged with any other native symbols. So I think the API should be targeted to clients that can synthesize a common symbol, which means having a single prevailing symbol and ignoring all others. On the other hand, there are clients (i.e. gold) that need the common symbol in the native object file, so maybe this can be a feature of lib/LTO until we have a chance to do something more principled in a way that would be compatible with gold (e.g. the gold plugin could use MC to create its own native object file with the common symbol resolutions). |
I noticed that what the existing gold-plugin support does is treat either all as prevailing or none as prevailing - it tracks whether any was prevailing in the CommonResolution structure, and doesn't create a new merged common if none were. Perhaps that should be done here, but I'm not sure when the linker would decide none was prevailing?