o.j.sivart at gmail.com
2010-May-13 04:53 UTC
[LLVMdev] Handling of thread_local globals by llc -march=cpp
Hi all, I've been exploring thread local globals in llvm and as part of this investigation I ran llc -march=cpp over a trivial llvm bc file which uses thread local storage for a global. For some reason llc -march=cpp seems to ignore the thread_local and produce code to create a standard global. Is this expected behaviour, a known limitation, or otherwise? Thanks in advance. Details are as follows. The llvm bc I'm using (which clang produced from a simple c source file, thread_local.c, that has a __thread global, a, and a single function, f, which returns the value of the thread local global) is: ; ModuleID = 'thread_local.c' target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32" target triple = "i386-pc-linux-gnu" @a = thread_local global i32 1, align 4 ; <i32*> [#uses=1] define i32 @f() nounwind { entry: %retval = alloca i32, align 4 ; <i32*> [#uses=2] %tmp = load i32* @a ; <i32> [#uses=1] store i32 %tmp, i32* %retval %0 = load i32* %retval ; <i32> [#uses=1] ret i32 %0 } Within the cpp file the relevant code to create and initialise the global is: GlobalVariable* gvar_int32_a = new GlobalVariable(/*Module=*/*mod, /*Type=*/IntegerType::get(mod->getContext(), 32), /*isConstant=*/false, /*Linkage=*/GlobalValue::ExternalLinkage, /*Initializer=*/0, // has initializer, specified below /*Name=*/"a"); gvar_int32_a->setAlignment(4); // Constant Definitions ConstantInt* const_int32_2 = ConstantInt::get(mod->getContext(), APInt(32, StringRef("1"), 10)); // Global Variable Definitions gvar_int32_a->setInitializer(const_int32_2); As you can see no actual parameter is provided for the optional formal ThreadLocal parameter of the GlobalVariable constructor; it instead then gets the default value of false. Compiling the cpp file and executing it to check the output of running the createPrintModulePass confirms that the llvm IR produced does not create a thread local global variable: ; ModuleID = 'thread_local.s' target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32" target triple = "i386-pc-linux-gnu" @a = global i32 1, align 4 ; <i32*> [#uses=1] define i32 @f() nounwind { entry: %retval = alloca i32, align 4 ; <i32*> [#uses=2] %tmp = load i32* @a ; <i32> [#uses=1] store i32 %tmp, i32* %retval %0 = load i32* %retval ; <i32> [#uses=1] ret i32 %0 }
Anton Korobeynikov
2010-May-13 07:43 UTC
[LLVMdev] Handling of thread_local globals by llc -march=cpp
Hello> I've been exploring thread local globals in llvm and as part of this investigation I ran llc -march=cpp over a trivial llvm bc file which uses thread local storage for a global. For some reason llc -march=cpp seems to ignore the thread_local and produce code to create a standard global. Is this expected behaviour, a known limitation, or otherwise?Thanks for the report. Should be fixed in r103702 -- With best regards, Anton Korobeynikov Faculty of Mathematics and Mechanics, Saint Petersburg State University
o.j.sivart at gmail.com
2010-May-13 09:05 UTC
[LLVMdev] Handling of thread_local globals by llc -march=cpp
Thanks for the quick reply and fix. Now it just means I have to hunt further in exploring why, in my simple test program, replacing the following line of code: GlobalVariable* global = new GlobalVariable(*MyModule, IntegerType::get(getGlobalContext(), 32), false, GlobalValue::ExternalLinkage, 0, "global"); with the following line of code: GlobalVariable* global = new GlobalVariable(*MyModule, IntegerType::get(getGlobalContext(), 32), false, GlobalValue::ExternalLinkage, 0, "global", 0, true); in order to create a thread local global variable instead of a standard global variable causes the function (which uses the global) produced by the following line of code: void *FPtr = MyExecutionEngine->getPointerToFunction(MyFunction); to segfault when I call it in the following sequence of code: int (*FP)() = (int (*)())FPtr; int res = FP(); when the function executes correctly in the case of instead having created a standard global variable. Doh! As far as I got with this was to note that the machine code produced for the function is attempting to still do a move from a memory location (and an inaccessible one at that: 0xfffffffc) instead of doing a move from an offset from the segment register. On 13/05/2010, at 5:13 PM, Anton Korobeynikov wrote:> Hello > >> I've been exploring thread local globals in llvm and as part of this investigation I ran llc -march=cpp over a trivial llvm bc file which uses thread local storage for a global. For some reason llc -march=cpp seems to ignore the thread_local and produce code to create a standard global. Is this expected behaviour, a known limitation, or otherwise? > Thanks for the report. Should be fixed in r103702 > > -- > With best regards, Anton Korobeynikov > Faculty of Mathematics and Mechanics, Saint Petersburg State University
Possibly Parallel Threads
- [LLVMdev] Handling of thread_local globals by llc -march=cpp
- [LLVMdev] Handling of thread_local globals by llc -march=cpp
- [LLVMdev] Handling of thread_local globals by llc -march=cpp
- [LLVMdev] Handling of thread_local globals by llc -march=cpp
- [LLVMdev] Handling of thread_local globals by llc -march=cpp