This is an archive of the discontinued LLVM Phabricator instance.

Clang/driver: emulated TLS mode.
ClosedPublic

Authored by chh on Jun 17 2015, 4:42 PM.

Diff Detail

Event Timeline

chh updated this revision to Diff 27896.Jun 17 2015, 4:42 PM
chh retitled this revision from to Implement target independent TLS compatible with glibc's emutls.c..
chh updated this object.
chh edited the test plan for this revision. (Show Details)
chh retitled this revision from Implement target independent TLS compatible with glibc's emutls.c. to Clang/driver: emulated TLS mode..Jun 17 2015, 5:06 PM
chh added a reviewer: enh.
chh removed a reviewer: enh.Jun 18 2015, 5:00 PM
chh added a subscriber: enh.
chh added a subscriber: Unknown Object (MLST).Jun 24 2015, 5:17 PM

I do not know enough about TLS modes to comment on much of this. The
attribute-specific stuff looks good to me, with one exception:

Index: docs/AttributeReference.rst

  • docs/AttributeReference.rst

+++ docs/AttributeReference.rst
@@ -743,6 +743,7 @@

  • local-dynamic
  • initial-exec
  • local-exec

+* emulated

Please do not modify AttributeReference.rst directly; just AttrDocs.td.

Thanks!

~Aaron

chh updated this revision to Diff 28683.Jun 29 2015, 10:07 AM
chh edited edge metadata.

Aaron, I uploaded a second patch which does not change AttributeReference.rst.
Thanks.

joerg added a subscriber: joerg.Jun 29 2015, 11:12 AM

Why do we need this? Shouldn't the backend translate whatever TLS access it finds into the emulation? I really would like to see some context for this change.

chh added a comment.Jun 29 2015, 12:20 PM

This patch should keep the default clang/llvm configuration for all targets, but add the necessary -ftls-model=emulated flag for Android users that need TLS.
Please see also the comments in the llvm bug:
https://llvm.org/bugs/show_bug.cgi?id=23566#c4

chh added a comment.Jun 29 2015, 1:45 PM

I see your question now. At the beginning I was looking for a way to set up
some configuration flag too for *-*-android targets to tell LLVM how to
lower TLS code. Trying to recognize "android" environment in LLVM seems too
restricted, as the emulated model could be useful to any target.

The existing -ftls-model looks like a natural hook to me.
This allows any target to support multiple TLS models and let users choose
which model to compile. The attribute((tls_model(...)) syntax seems
also a nice feature to keep, so I added the "emulated" mode into both
-ftls-model and tls_model attributes. As you can see in this patch and the
other LLVM patch, I was testing multiple models at the same time.

chh added a comment.Jul 13 2015, 11:10 AM

Here is Joerg's comment sent to llvm-commits@ but somehow did not reach here:

Date: Tue, 30 Jun 2015 13:03:13 +0200
From: Joerg Sonnenberger <joerg@britannica.bec.de>
To: llvm-commits@cs.uiuc.edu
Subject: Re: [PATCH] Clang/driver: emulated TLS mode.
Message-ID: <20150630110313.GA17930@britannica.bec.de>
Content-Type: text/plain; charset=us-ascii

On Mon, Jun 29, 2015 at 01:45:25PM -0700, Chih-hung Hsieh wrote:

I see your question now. At the beginning I was looking for a way to set up
some configuration flag too for *-*-android targets to tell LLVM how to
lower TLS code. Trying to recognize "android" environment in LLVM seems too
restricted, as the emulated model could be useful to any target.

Having a codegen flag to enable the translation of TLS access via the
emulation pass would be an option, but for that the pass should exist
first.

The existing -ftls-model looks like a natural hook to me.
This allows any target to support multiple TLS models and let users choose
which model to compile. The attribute((tls_model(...)) syntax seems
also a nice feature to keep, so I added the "emulated" mode into both
-ftls-model and tls_model attributes. As you can see in this patch and the
other LLVM patch, I was testing multiple models at the same time.

I don't think multiple TLS models in the sense of "native" vs "emultls"
is something that makes sense. TLS emulation is pretty much a crude hack
to workaround limitations either in the OS environment (Android) or the
toolchain (for NetBSD: VAX and Sun2). Given all the associated
complications, it would be insane to force the emulation path when
native TLS exists. Note that GCC supports different dialects for TLS
access on some platforms like ARM, but those are more like optimised
sequences.

chh added a comment.Jul 13 2015, 11:41 AM

I agree that this is a less optimal, or you can say backward or "temporary", solution in llvm to support emutls. The important benefit now is to allow switching of a few core Android modules from gcc to clang/llvm sooner, as we cannot fix Android linker in time or upgrade all old Android devices for new TLS applications. Note that this is not only an Arm target issue but all major Android targets.

But Android's linker might have ELF TLS support in the future. I see no alternative for llvm to support emutls for current Android and there might be a time in the future Android users will need choices to continue using emutls (with gcc or llvm) or native TLS with llvm.

As emutls is target independent, in http://reviews.llvm.org/D10522, it is added as a new IL TLS mode. Of course it could also be completely implement in clang front-end and be translated to IL that contains no reference to special TLS get_address IL. That seems a more complicated implementation to me, or did I miss something?
Is there a similar front-end translation pass in clang that I can learn or reuse for emutls?

rnk added a subscriber: rnk.Jul 14 2015, 9:33 AM

How does GCC do expose this model? Do they support __attribute__((tls_model("emulated"))), or is it a backend option like Joerg is suggesting?

If we go the backend option route, it doesn't have to be specific to Android, we can have some target predicate that can change in the future like useGCCEmulatedTLS().

test/CodeGenCXX/cxx11-thread-local.cpp
3

You can avoid duplicating the CHECK lines by giving FileCheck multiple prefixes:

| FileCheck --check-prefix=COMMON --check-prefix=EMU %s
chh added a comment.Jul 14 2015, 12:01 PM

Thanks for the suggestion about FileCheck prefixes.
I will simplify the code soon.

Gcc has configuration flags to enable or disable TLS.
It's emutls model/pass can be selected through configuration:

https://github.com/gcc-mirror/gcc/blob/master/gcc/tree-emutls.c

I have not found a compile time flag to select emulated vs native TLS models,
although that should be doable.

When Android gcc is configured to use the emulated TLS model,
TLS attributes like attribute((tls_model("local-dynamic")))
are silently ignored. The emulated model is used.
Lacking warning is bad, and it might be accepted only
when a target really cannot support both native and native TLS.

Android supports only emulated TLS now, but should be able to support both
in the future. To replace Android gcc with llvm, I would really like to have
a compile time flag instead of two copies of Android llvm to support/test
both TLS models. The -ftls-model seems to be the flag to add such a feature.
Then it follows to allow 5 tls_model attributes.

I see that clang's -ftls-model flag sets default, but does not overwrite
attribute((tls_model("local-dynamic"))). So I think an easy
implementation is to do the same for the -ftls-model=emulated flag.

The alternative is a new compile-time flag to enable emulated TLS and overrides all other 4 native tls_model attributes, and give warnings. This new flag will be needed at both clang/driver level and llvm IL level, right? Is that what you want? Any suggestion for the name or mechanism?

mingw on Windows uses emutls, so an option to do the same makes sense, maybe even the default to keep compatibility.

rnk added a comment.Jul 14 2015, 2:32 PM

I don't think it's necessary to warn on the local_exec, etc models. Those flags still provide information about how visible the TLS is, we just don't use it.

It sounds like we should have a -f flag, like -femulated-tls, that controls what we do. The default for Android and MinGW would be to enable it, and that could change over time.

Chandler thinks that this emulation should be done in Clang IRGen, but Nick and I disagree that this should happen late in LLVM. I suggested it could be an IR codegen preparation pass, but David Majnemer disagreed because then it's harder to CSE the call to compute the address of the TLS. Then again, the IR lowering you already have doesn't support CSE, and I think that's fine.

chh added a comment.Jul 14 2015, 3:47 PM

Reid, -femulated-tls and the defaults sound good to me.

I don't know much of clang's other passes yet. I made the emulated mode as similar to other 4 modes as possible and it seemed to be the easiest approach for me.

Could you tell me the best way to pass the -femulated-tls to llvm backend?

With -femulated-tls, we don't need attribute tls_model("emulated").
(1) If other tls_model attributes found by clang are passed to llvm, e.g., as thread_local(localexec) attribute, llvm will need a separate flag to process them like thread_local(emulated) attribute. Would this be a per compilation unit flag?
(2) If clang converts all other tls_model attributes and the default to thread_local(emulated) for llvm, we can use most of http://reviews.llvm.org/D10522 as is, and llvm can handle 5 TLS modes in one compilation unit.

rnk added a comment.Jul 14 2015, 4:06 PM
In D10524#205066, @chh wrote:

Could you tell me the best way to pass the -femulated-tls to llvm backend?

Because of LTO, we generally don't have a place for codegen options to live on the module. Probably a string attribute "emulated-tls" or "tls-emulation" on the GlobalVariable would be the way to go.

chh added a comment.Jul 14 2015, 5:22 PM

So in IR, a global variable can have string attributes like

thread_local emulated-tls
thread_local(localdynamic) emulated-tls
thread_local(initialexec) emulated-tls
thread_local(localexec) emulated-tls

I can give it a try.
Not sure yet if that will have shorter or longer patch.

chh updated this revision to Diff 29973.Jul 16 2015, 8:26 PM

Diff 3 simplified the clang front-end and driver changes:

  • Only -femulated-tls and -fno-emulated-tls flags are added. Default is -fno-emulated-tls mode.
  • Unit tests are modified to check:
    • C uninitialized global variables are common, but uninitialized thread local variables are not.
    • The -femulated-tls and -fno-emulated-tls flags are passed from clang to cc1.
rnk added inline comments.Jul 22 2015, 4:13 PM
include/clang/Driver/Options.td
515

This doesn't need to be a cc1 option, we can have just -femulated-tls for cc1 and remove the negative one in the driver.

lib/Driver/Tools.cpp
3955–3956

Generally we try to canonicalize flags in the driver rather than in cc1. Rather than doing this, how about something like the following:

// Emulated TLS is enabled by default on Android, and can be enabled manually with -femulated-tls.
bool EmulatedTLSDefault = Triple.getEnvironment() == llvm::Triple::Android;
if (Args.hasFlag(options::OPT_femulated_tls, options::OPT_fno_emulated_tls, EmulatedTLSDefault))
  CmdArgs.push_back("-femulated-tls");
test/CodeGen/tls-model.c
7

We try to use %clang_cc1 outside of driver tests. We can check for the -femulated-tls flag easily in the driver, and then use the cc1 interface directly.

8–17

We only need the first test for CodeGen.

chh updated this revision to Diff 30544.Jul 23 2015, 5:08 PM
chh marked 3 inline comments as done.

I might guess wrong the suggested changes.
Please check if the new diff is what you suggested.
Thanks.

rnk accepted this revision.Jul 27 2015, 2:59 PM
rnk added a reviewer: rnk.

lgtm

test/CodeGenCXX/cxx11-thread-local.cpp
2

I also meant for this comment to apply here:
"We try to use %clang_cc1 outside of driver tests. We can check for the -femulated-tls flag easily in the driver, and then use the cc1 interface directly."

This revision is now accepted and ready to land.Jul 27 2015, 2:59 PM
chh added inline comments.Jul 27 2015, 5:18 PM
test/CodeGenCXX/cxx11-thread-local.cpp
2

Sure. I will fix that before submit.

This revision was automatically updated to reflect the committed changes.