[LLVMdev] About thread_local in 3.0
Jianzhou Zhao
jianzhou at seas.upenn.edu
Wed Jul 4 06:25:15 PDT 2012
Hi LLVM,
I am using 3.0, and I have a question about the __thread in c and
thread_local in LLVM IR: O1-O4 and the final linked code behave
differently.
////////////////////////////////////
The following C code is from the LLVM testcase
(SingleSource/UnitTests/Threads/2010-12-08-tls.c)
#include <stdio.h>
__thread int a = 4;
int foo (void)
{
return a;
}
int main (void) {
printf("a is %d\n", foo());
return 0;
}
It contains a __thread attribute. Both GCC's output program and
clang's produce "a is 4", and then return. The command line options
are the default.
gcc 2010-12-08-tls.c
clang 2010-12-08-tls.c
////////////////////////////////////
The following code (2010-12-08-tls.O1.ll) is generated by
clang -c -O1 -emit-llvm 2010-12-08-tls.c -o 2010-12-08-tls.O1.bc
llvm-dis 2010-12-08-tls.O1.bc
@a = thread_local global i32 4, align 4
@.str = private unnamed_addr constant [9 x i8] c"a is %d\0A\00", align 1
define i32 @foo() nounwind readonly {
%1 = load i32* @a, align 4, !tbaa !0
ret i32 %1
}
define i32 @main() nounwind {
%1 = tail call i32 @foo()
%2 = tail call i32 (i8*, ...)* @printf(i8* getelementptr inbounds
([9 x i8]* @.str, i32 0, i32 0), i32 %1) nounwind
ret i32 0
}
declare i32 @printf(i8* nocapture, ...) nounwind
!0 = metadata !{metadata !"int", metadata !1}
!1 = metadata !{metadata !"omnipotent char", metadata !2}
!2 = metadata !{metadata !"Simple C/C++ TBAA", null}
If I jit the code, say "lli 2010-12-08-tls.O1.bc", I got
0 lli 0x091ac1a8
1 lli 0x091ac7e7
2 0xffffe400 + 0
3 lli 0x08f7a103
llvm::ExecutionEngine::runFunctionAsMain(llvm::Function*,
std::vector<std::string, std::allocator<std::string> > const&, char
const* const*) + 1459
4 lli 0x0861df9e main + 3374
5 libc.so.6 0xb75b7ace __libc_start_main + 254
Stack dump:
0. Program arguments: lli 2010-12-08-tls.O4.bc
Segmentation fault
If I lli the code, say "lli --force-interpreter=true
2010-12-08-tls.O1.bc", I got
"a is 24"
////////////////////////////////////
The following code (2010-12-08-tls.O4.ll) is generated by
clang -c -O4 -emit-llvm 2010-12-08-tls.c -o 2010-12-08-tls.O4.bc
llvm-dis 2010-12-08-tls.O4.bc
@a = thread_local global i32 4, align 4
@.str = private unnamed_addr constant [9 x i8] c"a is %d\0A\00", align 1
define i32 @foo() nounwind readonly {
%1 = load i32* @a, align 4, !tbaa !0
ret i32 %1
}
define i32 @main() nounwind {
%1 = load i32* @a, align 4, !tbaa !0
%2 = tail call i32 (i8*, ...)* @printf(i8* getelementptr inbounds
([9 x i8]* @.str, i32 0, i32 0), i32 %1) nounwind
ret i32 0
}
declare i32 @printf(i8* nocapture, ...) nounwind
!0 = metadata !{metadata !"int", metadata !1}
!1 = metadata !{metadata !"omnipotent char", metadata !2}
!2 = metadata !{metadata !"Simple C/C++ TBAA", null}
We can see, O4 does inlining, but otherwise its output is the same to
O1's. And I got the same results from jit and lli.
////////////////////////////////////
The following code (2010-12-08-tls.ld.ll) is generated by
opt -std-link-opt 2010-12-08-tls.O1.bc -o 2010-12-08-tls.ld.bc
llvm-dis 2010-12-08-tls.ld.bc
@.str = private unnamed_addr constant [9 x i8] c"a is %d\0A\00", align 1
define i32 @main() nounwind {
%1 = tail call i32 (i8*, ...)* @printf(i8* getelementptr inbounds
([9 x i8]* @.str, i32 0, i32 0), i32 4) nounwind
ret i32 0
}
declare i32 @printf(i8* nocapture, ...) nounwind
We can see link-opt value-numbered %1 with 4. Now, jit and lli produce
the results "a is 24", which is same to clang and gcc's native
output's. I am not familiar with thread_local and the __thread in C,
was wondering if this is the expected behavior of thread_local.
Thanks.
--
J
More information about the llvm-dev
mailing list