[llvm-dev] [RFC] lld: Dropping TLS relaxations in favor of TLSDESC

Rafael Avila de Espindola via llvm-dev llvm-dev at lists.llvm.org
Tue Nov 7 20:16:56 PST 2017


Rui Ueyama <ruiu at google.com> writes:

>> So I am strongly against removing either non TLSDESC support of support
>> for the relaxations.
>>
>
> It's still pretty arguable. By default, compilers use General Dynamic model
> with -fpic, and Initial Exec without -fpic.

It is more complicated than that. You can get all 4 modes with clang

-------------------------------
__thread int bar = 42;
int *foo(void) {  return &bar; }
-------------------------------
without -fPIC: local exec.

-------------------------------
extern __thread int bar;
int *foo(void) {  return &bar; }
-------------------------------
without -fPIC: initial exec.
with -fPIC: general dynamic

-------------------------------
__attribute__((visibility("hidden"))) extern __thread int bar;
int *foo(void) {  return &bar; }
-------------------------------
with -fPIC: local dynamic.

> lld doesn't do any relaxation
> if -shared is given. So, if you are creating a DSO, thread-local variables
> in the DSO are accessed using Global Dynamic model. No relaxations are
> involved.

There is not a lot of opportunities there. If one patches one access at
a time LD is as expensive as GD. The linker also doesn't know if the .so
will be used with dlopen or not, sot it cannot relax to IE. I guess a
linker could have that command line option for the second part.

Now that I spell that out, it is easy to see the TLSDESC big
advantage. It can optimize the case the static linker cannot.

> If you are creating an executable and if your executable is not
> position-independent, you're using Initial Exec model by default which is
> as fast as variables accessed through GOT. If you really want to use Local
> Exec model, you can pass -ftls-model=local-exec to compilers.

But then all the used variables have to be defined in the same
executable. You can't have even one from a shared library (think errno).

The nice thing about linker relaxations is that they are very user
friendly. The linker is the first point in the toolchaing where some
usefull fact is know, and it can optimize the result with no user
intervention.

> So I don't see a strong reason to do a complicated instruction rewriting in
> the linker. I feel more like we should do whatever it is instructed to do
> by command line options and input object files. You are for example free to
> pass the -fPIC option to create object files and still let the linker to
> create a non-PIC executable, even though these combinations doesn't make
> much sense and produces slightly inefficient binary. If you don't like it,
> you can fix the compiler options. Thread-local variables can be considered
> in the same way, no?

They are considered in the same way, we also relax got access :-)

The proposal is making the linker worse for our users to make our lifes
easier. I really don't think we should do it.

It is likelly that we can code the existing optimization in a simpler
way. Even if we cannot, I don't think we should remove them.

Linker relaxations are extremely convenient. We use the example you
gave (-fPIC .o in an executable) all the time in llvm. That way we build
only one .o that is used in lib/ and bin/.

Linker relaxations are also fundamental to how RISCV works.

Cheers,
Rafael


More information about the llvm-dev mailing list