Jump to content

LLVM Compiler/OpenMP Support

From Wikibooks, open books for an open world

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.

https://openmp.llvm.org/


installation

[edit | edit source]

cmake -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

[edit | edit source]

Hello example

[edit | edit source]
cat 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 | edit source]
#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

[edit | edit source]

List

  • 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

[edit | edit source]

First, 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