LLVM Clang - Advancing Compiler Technology
LLVM Clang - Advancing Compiler Technology
Applications of LLVM
• OpenGL, OpenCL, Python, Ruby, etc, even RealBasic and Cray Fortran
http://llvm.org/
Why new compilers?
Existing open source C compilers have stagnated!
– Based on decades old code generation technology
– Aging code bases: difficult to learn, hard to change substantially
– Not modular, can’t be reused in many other applications
– Keep getting slower with every release
• What I want:
– A set of production-grade reusable libraries
– ... which implement the best known techniques
– ... which focus on compile time
– ... and performance of the generated code
http://llvm.org/
LLVM Vision and Approach
• Primary mission: build a set of modular compiler components:
– Reduces the time & cost to construct a particular compiler
• A new compiler = glue code plus any components not yet available
– Components are shared across different compilers
• Improvements made for one compiler benefits the others
– Allows choice of the right component for the job
• Don’t force “one true register allocator”, scheduler, or optimization order
DWARF Target
Code Optzn linker ...
JIT IPO
gen
http://llvm.org/docs/
http://llvm.org/
Example Application:
LLVM + OpenGL
Colorspace Conversion
• Code to convert from one color format to another:
– e.g. BGRA444R to RGBA 8888
– Hundreds of combinations, importance depends on input
void main() {
vec3 ecPosition = vec3(gl_ModelViewMatrix * gl_Vertex);
vec3 tnorm = normalize(gl_NormalMatrix * gl_Normal);
vec3 lightVec = normalize(LightPosition - ecPosition);
vec3 reflectVec = reflect(-lightVec, tnorm);
vec3 viewVec = normalize(-ecPosition);
float diffuse = max(dot(lightVec, tnorm), 0.0);
float spec = 0.0;
if (diffuse > 0.0) {
spec = max(dot(reflectVec, viewVec), 0.0);
spec = pow(spec, 16.0);
}
LightIntensity = DiffuseContribution * diffuse +
SpecularContribution * spec;
MCposition = gl_Vertex.xy;
gl_Position = ftransform();
}
http://llvm.org/
OpenGL Pixel/Vertex Shader (GLSL)
OpenGL Implementation Before LLVM
• Custom JIT for X86-32 and PPC-32:
– Very simple codegen: pasted chunks of AltiVec or SSE code
– Little optimization across operations (e.g. scheduling)
– Very fragile, hard to understand and change (hex opcodes)
• Interpreter:
– JIT didn’t support all OpenGL features: fallback to interpreter
– Interpreter was very slow, 100x or worse than JIT
GPU
GLSL
OpenGL
Text Shader Custom JIT
Parser
Interpreter
http://llvm.org/
OpenGL JIT Built with LLVM Components
GLSL
OpenGL OpenGL to LLVM LLVM
Text Shader
Parser LLVM Optimizer JIT
while (...) {
...
switch (cur_opcode) {
case dotproduct: result = opengl_dot(lhs, rhs); break;
case texturelookup: result = opengl_texlookup(lhs, rhs); break;
case ...
http://llvm.org/
OpenGL to LLVM: At runtime
1. Translate OpenGL AST into LLVM call instructions: one per operation
2. Use the LLVM inliner to inline opcodes from precompiled bytecode
3. Optimize/codegen as before
OpenGL
... to LLVM ...
vec3 viewVec = normalize(-ecPosition); %tmp1 = call opengl_negate(ecPosition)
float diffuse = max(dot(lightVec, tnorm), 0.0); %viewVec = call opengl_normalize(%tmp1);
... %tmp2 = call opengl_dot(%lightVec, %tnorm)
%diffuse = call opengl_max(%tmp2, 0.0);
...
http://llvm.org/
Lots of Other Applications
• OpenCL: a GPGPU language, with most vendors using LLVM
• Dynamic Languages: Unladen Swallow, Rubinious, MacRuby
• llvm-gcc 4.2 & DragonEgg
• Cray Cascade Fortran Compiler
• vmkit: Java and .NET VMs
• Haskell, Mono, LDC, Pure, Roadsend PHP, RealBasic
• IOQuake3 for real-time raytracing of Quake!
http://llvm.org/Users.html
http://llvm.org/
Clang Compiler
Clang Goals
• Unified parser for C-based languages
– Language conformance (C, Objective-C, C++)
– Useful error and warning messages
• Multi-purpose
– Indexing, static
analysis, code generation
– Source to source tools, refactoring
http://clang.llvm.org/
Clang Goals #2
• High performance!
– Low memory footprint, fast compiles
– Support lazy evaluation, caching, multithreading
– get the compiler out of the way during development
http://clang.llvm.org/
Clang Compiler Status
• C, Objective-C, and C++ support are production quality
– Clang has successfully compiled millions of lines of C/C++/Objective-C code
– Can bootstrap itself, build Boost, Mozilla, and many other “compiler busters”
– Builds a working FreeBSD base system
– Interesting tools starting to be built on it
http://clang.llvm.org/
Compile Time Comparison: Front-end
PostgreSQL: a medium sized C project: 619 C Files in 665K LOC, excluding headers
50s 48.9s
40s
23.93s
e r !
as t
x f
30s
2.3
21.6s
20s
6.91s
25.07s
10s
14.70s
http://clang.llvm.org/performance.html http://clang.llvm.org/
SPEC INT 2000 Optimizer Compile Times
200s
Lower is Better
187s
GCC 4.2
LLVM 164s
160s
144s
133s 131s
126s
120s 112s 42% Faster Faster than
30% Faster at -O3! GCC at -O2!
at -O2!
80s
18% Faster
at -O1!
40s
0s
0s
-O1 -O2 -O3 -O4: LTO
http://clang.llvm.org/
SPEC INT 2000 Execution Time
Relative to GCC -O2: Lower is Better
100%
100.0%
GCC 4.2
LLVM
96.4%
95% 95.1%
5% Faster 92.5%
90% at -O2!
4% Faster
at -O3!
85%
20% Faster
than -O2!
80% 80.3%
75%
-O2 -O3 -O4 (LTO)
http://clang.llvm.org/
User Experience: Diagnostics
% gcc-4.2 t.c
t.c: In function 'test1':
t.c:5: error: invalid type argument of 'unary *'
t.c:6: error: invalid operands to binary +
http://clang.llvm.org/
User Experience: “Expressive” Diagnostics
• Other Features:
– std::string instead of std::basic_string<char, std::char_traits<char>, std::allocator<char> >
– #pragma control over diagnostics
– Doesn’t “pretty print” expressions back out at you
% clang test.c
t.c:5:13: error: indirection requires pointer operand ('int' invalid)
intArg += *(someA.X);
^~~~~~~~~~
t.c:6:49: error: invalid operands to binary expression ('int' and 'struct A')
return intArg + func(intArg ? ((someA.X+40) + someA) / 42 + someA.X : someA.X));
~~~~~~~~~~~~ ^ ~~~~~
% gcc-4.2 t.c
t.c: In function 'test1':
t.c:5: error: invalid type argument of 'unary *'
t.c:6: error: invalid operands to binary +
http://clang.llvm.org/
Other Improvements
$ g++-4.2 t.cpp
t.cpp:12: error: no match for 'operator=' in 'str = vec'
$ clang t.cpp
t.cpp:12:7: error: incompatible type assigning 'vector<Real>', expected
'std::string' (aka 'class std::basic_string<char>')
str = vec;
^ ~~~
t.c:48:7: error: invalid operands to binary expression ('int' and 'struct A')
X = MAX(X, *Ptr);
^~~~~~~~~~~~
http://clang.llvm.org/diagnostics.html http://clang.llvm.org/
Clang Static Analyzer
• Automaticallyfinds and reports bugs in your code
• Uses deep analysis techniques to explore things that testing misses
http://clang-analyzer.llvm.org/ http://clang.llvm.org/
Other Notable LLVM Projects
• MC: Machine Code slicing and dicing
– Assemblers, disassemblers, object file processing
http://llvm.org/devmtg/2010-11/ http://llvm.org/
LLVM and Clang
• Compiler infrastructure built with reusable components
– Bringing compiler techniques to new interesting problems