LLVM Compiler/OpenMP Support
With the release of Clang 3.8.0, OpenMP 3.1 support is enabled in Clang by default, and the OpenMP runtime is therefore built as a normal part of the Clang build, and distributed with the binary distributions. You do not, therefore, need explicitly to check out this code, or build it out of tree; a normal Clang check out and build will automatically include building these runtime libraries.
installation
editcmake -G Ninja -DCMAKE_BUILD_TYPE=RELEASE -DCMAKE_INSTALL_PREFIX=$LLVM_PATH -DLLVM_ENABLE_PROJECTS="clang;clang-tools-extra;compiler-rt;openmp" -DCLANG_BUILD_EXAMPLES=1 $LLVM_SRC/llvm
ninja install -j8 -l8
OpenMP lowering or Code Geneneration
editHello example
editcat omp_hello.c #include <omp.h> #include <stdio.h> int main (int argc, char *argv[]) { int nthreads, tid; #pragma omp parallel private(nthreads, tid) { tid = omp_get_thread_num(); printf("Hello World from thread = %d\n", tid); } }
clang -fopenmp -S -O3 -emit-llvm omp_hello.c
cat omp_hello.ll
1 ; ModuleID = 'omp_hello.c' 2 source_filename = "omp_hello.c" 3 target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" 4 target triple = "x86_64-unknown-linux-gnu" 5 6 %struct.ident_t = type { i32, i32, i32, i32, i8* } 7 8 @.str = private unnamed_addr constant [30 x i8] c"Hello World from thread = %d\0A\00", align 1 9 @.str.1 = private unnamed_addr constant [23 x i8] c";unknown;unknown;0;0;;\00", align 1 10 @0 = private unnamed_addr global %struct.ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* @.str.1, i32 0, i32 0) }, align 8 11 12 ; Function Attrs: nounwind uwtable 13 define dso_local i32 @main(i32 %argc, i8** nocapture readnone %argv) local_unnamed_addr #0 { 14 entry: 15 tail call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* nonnull @0, i32 0, void (i32*, i32*, ...)* bitcast (void (i32*, i32*)* @.omp_outlined. to void (i32*, i32*, ...)*)) #4 16 ret i32 0 17 } 18 19 ; Function Attrs: norecurse nounwind uwtable 20 define internal void @.omp_outlined.(i32* noalias nocapture readnone %.global_tid., i32* noalias nocapture readnone %.bound_tid.) #1 { 21 entry: 22 %call = tail call i32 @omp_get_thread_num() #4 23 %call1 = tail call i32 (i8*, ...) @printf(i8* nonnull dereferenceable(1) getelementptr inbounds ([30 x i8], [30 x i8]* @.str, i64 0, i64 0), i32 %call) 24 ret void 25 } 26 27 declare dso_local i32 @omp_get_thread_num() local_unnamed_addr #2 28 29 ; Function Attrs: nofree nounwind 30 declare dso_local i32 @printf(i8* nocapture readonly, ...) local_unnamed_addr #3 31 32 declare !callback !2 dso_local void @__kmpc_fork_call(%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) local_unnamed_addr
offloading example
edit#include <stdio.h> #include <omp.h> int main(void) { int isHost = 0; #pragma omp target map(from: isHost) { isHost = omp_is_initial_device(); } if (isHost < 0) { printf("Runtime error, isHost=%d\n", isHost); } // CHECK: Target region executed on the device printf("Target region executed on the %s\n", isHost ? "host" : "device"); return isHost; }
clang -fopenmp -S -O3 -emit-llvm -fopenmp-targets=nvptx64-nvidia-cuda offloading_success.cpp
relevant source files
editList
- tests: clang/test/OpenMP
- Clang CodeGen for OpenMP IR:
- clang/lib/CodeGen/CGOpenMPRuntime.cpp
- clang/lib/CodeGen/CGStmtOpenMP.cpp //This contains code to emit OpenMP nodes as LLVM code.
- LLVM OMP IR Builder: llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
- Runtime support: openmp/runtime/src/kmp_csupport.cpp
How to Debug
editFirst, use -v to show the actual command line used by the clang driver:
clang -v -fopenmp omp_hello.c
clang version 10.0.1 (https://github.com/llvm/llvm-project d24d5c8e308e689dcd83cbafd2e8bd32aa845a15) Target: x86_64-unknown-linux-gnu Thread model: posix InstalledDir: /home/ubuntu/install/llvm_install/bin Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/7 Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/7.5.0 Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/8 Selected GCC installation: /usr/lib/gcc/x86_64-linux-gnu/7.5.0 Candidate multilib: .;@m64 Selected multilib: .;@m64 /home/ubuntu/install/llvm_install/bin/clang-10 -cc1 -triple x86_64-unknown-linux-gnu -emit-obj -mrelax-all -disable-free -main-file-name omp_hello.c -mrelocation-model static -mthread-model posix -mframe-pointer=all -fmath-errno -fno-rounding-math -masm-verbose -mconstructor-aliases -munwind-tables -target-cpu x86-64 -dwarf-column-info -fno-split-dwarf-inlining -debugger-tuning=gdb -v -resource-dir /home/ubuntu/install/llvm_install/lib/clang/10.0.1 -internal-isystem /usr/local/include -internal-isystem /home/ubuntu/install/llvm_install/lib/clang/10.0.1/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fdebug-compilation-dir /home/ubuntu -ferror-limit 19 -fmessage-length 0 -fopenmp -fgnuc-version=4.2.1 -fobjc-runtime=gcc -fdiagnostics-show-option -fcolor-diagnostics -faddrsig -o /tmp/omp_hello-c73985.o -x c omp_hello.c clang -cc1 version 10.0.1 based upon LLVM 10.0.1 default target x86_64-unknown-linux-gnu ignoring nonexistent directory "/include" #include "..." search starts here: #include <...> search starts here: /usr/local/include /home/ubuntu/install/llvm_install/lib/clang/10.0.1/include /usr/include/x86_64-linux-gnu /usr/include End of search list. "/usr/bin/ld" -z relro --hash-style=gnu --eh-frame-hdr -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o a.out /usr/lib/gcc/x86_64-linux-gnu/7.5.0/../../../x86_64-linux-gnu/crt1.o /usr/lib/gcc/x86_64-linux-gnu/7.5.0/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/7.5.0/crtbegin.o -L/usr/lib/gcc/x86_64-linux-gnu/7.5.0 -L/usr/lib/gcc/x86_64-linux-gnu/7.5.0/../../../x86_64-linux-gnu -L/lib/x86_64-linux-gnu -L/lib/../lib64 -L/usr/lib/x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/7.5.0/../../.. -L/home/ubuntu/install/llvm_install/bin/../lib -L/lib -L/usr/lib /tmp/omp_hello-c73985.o -lomp -lgcc --as-needed -lgcc_s --no-as-needed -lpthread -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/x86_64-linux-gnu/7.5.0/crtend.o /usr/lib/gcc/x86_64-linux-gnu/7.5.0/../../../x86_64-linux-gnu/crtn.o
Next, use gdb to debug the actual executable with the full command line options
- gdb -args /home/ubuntu/install/llvm_install/bin/clang-10 -cc1 -triple x86_64-unknown-linux-gnu -emit-obj -mrelax-all -disable-free -main-file-name omp_hello.c -mrelocation-model static -mthread-model posix -mframe-pointer=all -fmath-errno -fno-rounding-math -masm-verbose -mconstructor-aliases -munwind-tables -target-cpu x86-64 -dwarf-column-info -fno-split-dwarf-inlining -debugger-tuning=gdb -v -resource-dir /home/ubuntu/install/llvm_install/lib/clang/10.0.1 -internal-isystem /usr/local/include -internal-isystem /home/ubuntu/install/llvm_install/lib/clang/10.0.1/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fdebug-compilation-dir /home/ubuntu -ferror-limit 19 -fmessage-length 0 -fopenmp -fgnuc-version=4.2.1 -fobjc-runtime=gcc -fdiagnostics-show-option -fcolor-diagnostics -faddrsig -o /tmp/omp_hello-c73985.o -x c omp_hello.c
Warmup run of the compiler within gdb
- (gdb) r
Set a breakpoint at 1829 llvm::FunctionCallee CGOpenMPRuntime::createRuntimeFunction(unsigned Function)
- b CGOpenMPRuntime.cpp:1829
- r # run it
Now can check the backtrace/call stack
Breakpoint 1, clang::CodeGen::CGOpenMPRuntime::createRuntimeFunction (this=0x555565d75fd0, Function=0) at /home/ubuntu/source/llvm_src/clang/lib/CodeGen/CGOpenMPRuntime.cpp:1829 1829 llvm::FunctionCallee CGOpenMPRuntime::createRuntimeFunction(unsigned Function) { (gdb) bt #0 clang::CodeGen::CGOpenMPRuntime::createRuntimeFunction (this=0x555565d75fd0, Function=0) at /home/ubuntu/source/llvm_src/clang/lib/CodeGen/CGOpenMPRuntime.cpp:1829 #1 0x000055555af54a62 in clang::CodeGen::CGOpenMPRuntime::<lambda(clang::CodeGen::CodeGenFunction&, clang::CodeGen::PrePostActionTy&)>::operator()(clang::CodeGen::CodeGenFunction &, clang::CodeGen::PrePostActionTy &) const (__closure=0x7fffffff80a0, CGF=...) at /home/ubuntu/source/llvm_src/clang/lib/CodeGen/CGOpenMPRuntime.cpp:3109 #2 0x000055555af89801 in clang::CodeGen::RegionCodeGenTy::CallbackFn<clang::CodeGen::CGOpenMPRuntime::emitParallelCall(clang::CodeGen::CodeGenFunction&, clang::SourceLocation, llvm::Function*, llvm::ArrayRef<llvm::Value*>, const clang::Expr*)::<lambda(clang::CodeGen::CodeGenFunction&, clang::CodeGen::PrePostActionTy&)> >(intptr_t, clang::CodeGen::CodeGenFunction &, clang::CodeGen::PrePostActionTy &) (CodeGen=140737488322720, CGF=..., Action=...) at /home/ubuntu/source/llvm_src/clang/lib/CodeGen/CGOpenMPRuntime.h:76 #3 0x000055555af45212 in clang::CodeGen::RegionCodeGenTy::operator() (this=0x7fffffff8080, CGF=...) at /home/ubuntu/source/llvm_src/clang/lib/CodeGen/CGOpenMPRuntime.cpp:787 #4 0x000055555af55072 in clang::CodeGen::CGOpenMPRuntime::emitParallelCall (this=0x555565d75fd0, CGF=..., Loc=..., OutlinedFn=0x555565d0bf78, CapturedVars=..., IfCond=0x0) at /home/ubuntu/source/llvm_src/clang/lib/CodeGen/CGOpenMPRuntime.cpp:3145 #5 0x000055555aabd108 in emitCommonOMPParallelDirective (CGF=..., S=..., InnermostKind=llvm::omp::Directive::OMPD_parallel, CodeGen=..., CodeGenBoundParameters=...) at /home/ubuntu/source/llvm_src/clang/lib/CodeGen/CGStmtOpenMP.cpp:1329 #6 0x000055555aabdbbf in clang::CodeGen::CodeGenFunction::EmitOMPParallelDirective (this=0x7fffffff8880, S=...) at /home/ubuntu/source/llvm_src/clang/lib/CodeGen/CGStmtOpenMP.cpp:1439 #7 0x000055555aa94671 in clang::CodeGen::CodeGenFunction::EmitStmt (this=0x7fffffff8880, S=0x555565e22980, Attrs=...) at /home/ubuntu/source/llvm_src/clang/lib/CodeGen/CGStmt.cpp:193 #8 0x000055555aa95392 in clang::CodeGen::CodeGenFunction::EmitCompoundStmtWithoutScope (this=0x7fffffff8880, S=..., GetLast=false, AggSlot=...) at /home/ubuntu/source/llvm_src/clang/lib/CodeGen/CGStmt.cpp:444 #9 0x000055555ab1ff79 in clang::CodeGen::CodeGenFunction::EmitFunctionBody (this=0x7fffffff8880, Body=0x555565e229b8) at /home/ubuntu/source/llvm_src/clang/lib/CodeGen/CodeGenFunction.cpp:1146 #10 0x000055555ab20be3 in clang::CodeGen::CodeGenFunction::GenerateCode (this=0x7fffffff8880, GD=..., Fn=0x555565d0bd38, FnInfo=...) at /home/ubuntu/source/llvm_src/clang/lib/CodeGen/CodeGenFunction.cpp:1311 #11 0x000055555ab498d0 in clang::CodeGen::CodeGenModule::EmitGlobalFunctionDefinition (this=0x555565d73210, GD=..., GV=0x555565d0bd38) at /home/ubuntu/source/llvm_src/clang/lib/CodeGen/CodeGenModule.cpp:4474 #12 0x000055555ab42709 in clang::CodeGen::CodeGenModule::EmitGlobalDefinition (this=0x555565d73210, GD=..., GV=0x0) at /home/ubuntu/source/llvm_src/clang/lib/CodeGen/CodeGenModule.cpp:2864 #13 0x000055555ab4123f in clang::CodeGen::CodeGenModule::EmitGlobal (this=0x555565d73210, GD=...) at /home/ubuntu/source/llvm_src/clang/lib/CodeGen/CodeGenModule.cpp:2567 #14 0x000055555ab4d9a0 in clang::CodeGen::CodeGenModule::EmitTopLevelDecl (this=0x555565d73210, D=0x555565e20f20) at /home/ubuntu/source/llvm_src/clang/lib/CodeGen/CodeGenModule.cpp:5279 #15 0x000055555baa4537 in (anonymous namespace)::CodeGeneratorImpl::HandleTopLevelDecl (this=0x555565d72870, DG=...) at /home/ubuntu/source/llvm_src/clang/lib/CodeGen/ModuleBuilder.cpp:170 #16 0x000055555ba9de7a in clang::BackendConsumer::HandleTopLevelDecl (this=0x555565d72690, D=...) at /home/ubuntu/source/llvm_src/clang/lib/CodeGen/CodeGenAction.cpp:214 #17 0x000055555cf95464 in clang::ParseAST (S=..., PrintStats=false, SkipFunctionBodies=false) at /home/ubuntu/source/llvm_src/clang/lib/Parse/ParseAST.cpp:162 #18 0x000055555b1ba873 in clang::ASTFrontendAction::ExecuteAction (this=0x555565d52ac0) at /home/ubuntu/source/llvm_src/clang/lib/Frontend/FrontendAction.cpp:1043 #19 0x000055555ba9bd46 in clang::CodeGenAction::ExecuteAction (this=0x555565d52ac0) at /home/ubuntu/source/llvm_src/clang/lib/CodeGen/CodeGenAction.cpp:1179 #20 0x000055555b1ba1d4 in clang::FrontendAction::Execute (this=0x555565d52ac0) at /home/ubuntu/source/llvm_src/clang/lib/Frontend/FrontendAction.cpp:936 #21 0x000055555b14eb74 in clang::CompilerInstance::ExecuteAction (this=0x555565d4f490, Act=...) at /home/ubuntu/source/llvm_src/clang/lib/Frontend/CompilerInstance.cpp:965 #22 0x000055555b325e07 in clang::ExecuteCompilerInvocation (Clang=0x555565d4f490) at /home/ubuntu/source/llvm_src/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp:290 #23 0x0000555557d60900 in cc1_main (Argv=..., Argv0=0x7fffffffe2fb "/home/ubuntu/install/llvm_install/bin/clang-10", MainAddr=0x555557d541aa <GetExecutablePath[abi:cxx11](char const*, bool)>) at /home/ubuntu/source/llvm_src/clang/tools/driver/cc1_main.cpp:240 #24 0x0000555557d55a4c in ExecuteCC1Tool (ArgV=...) at /home/ubuntu/source/llvm_src/clang/tools/driver/driver.cpp:329 #25 0x0000555557d561ca in main (argc_=54, argv_=0x7fffffffdef8) at /home/ubuntu/source/llvm_src/clang/tools/driver/driver.cpp:403