alok created this revision.
alok added reviewers: jmorse, aprantl, djtodoro, jini.susan.
alok added a project: debug-info.
Herald added subscribers: guansong, yaxunl.
Herald added a project: All.
alok requested review of this revision.
Herald added a reviewer: jdoerfert.
Herald added subscribers: cfe-commits, sstefan1.
Herald added a project: clang.

In case of OpenMP programs, thread local variables can be present in any clause 
pertaining to
OpenMP constructs, as we know that compiler generates artificial functions and 
in some cases
values are passed to those artificial functions thru parameters.
 For an example, if thread local variable is present in copyin clause (testcase 
attached with the
patch), parameter with same name is generated as parameter to artificial 
function. When user
inquires the thread Local variable, its debug info is hidden by the parameter. 
The debug info
for parameters (for thread local) must be suppressed.

Without the patch, attached testcase behaves wrongly under debuggers.

  Thread 3 "a.out" hit Breakpoint 3, .omp_outlined._debug__ 
(.global_tid.=0x155547ffde20, .bound_tid.=0x155547ffde18, nt=@0x7fffffffe2b8: 
4, gbl_int=@0x15555553333c: 65)
      at simple.c:29
  29                  printf ("In parallel region total threads = %d, thread id 
= %d data=%d gbl_addr = %p\n", nt, tid, data, &gbl_int);
  (gdb) p tid
  $1 = 2
  (gdb) p &gbl_int
  $2 = (int *) 0x15555553333c
  (gdb) c
  Continuing.
  [Switching to Thread 0x155553ad2b80 (LWP 12279)]
  
  Thread 2 "a.out" hit Breakpoint 2, .omp_outlined._debug__ 
(.global_tid.=0x155553ad1de0, .bound_tid.=0x155553ad1dd8, nt=@0x7fffffffe2b8: 
4, gbl_int=@0x15555553333c: 65)
      at simple.c:27
  27                  printf ("In parallel region total threads = %d, thread id 
= %d data=%d gbl_addr = %p\n", nt, tid, data, &gbl_int);
  (gdb) p tid
  $3 = 1
  (gdb) p &gbl_int
  $4 = (int *) 0x15555553333c

Please note that same address is shown for all the threads which is wrong (for 
thread local variable).

With the current patch, the issue is fixed.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D123787

Files:
  clang/include/clang/AST/Decl.h
  clang/lib/CodeGen/CGDecl.cpp
  clang/lib/CodeGen/CGStmtOpenMP.cpp
  clang/test/OpenMP/debug_threadprivate_copyin.c

Index: clang/test/OpenMP/debug_threadprivate_copyin.c
===================================================================
--- /dev/null
+++ clang/test/OpenMP/debug_threadprivate_copyin.c
@@ -0,0 +1,59 @@
+// This testcase checks emission of debug info for threadprivate variables
+// present in any clause of OpenMP construct.
+
+// REQUIRES: x86_64-linux
+
+// RUN: %clang_cc1 -debug-info-kind=constructor -x c -verify -triple x86_64-pc-linux-gnu -fopenmp -emit-llvm %s -o - | FileCheck %s
+// expected-no-diagnostics
+
+// CHECK: define internal void @.omp_outlined._debug__(
+// CHECK: call void @llvm.dbg.declare(metadata i32** %.global_tid..addr,
+// CHECK: call void @llvm.dbg.declare(metadata i32** %.bound_tid..addr,
+// CHECK: call void @llvm.dbg.declare(metadata i32** %nt.addr
+// CHECK: store i32* %gbl_dynamic_int, i32** %gbl_dynamic_int.addr, align 8
+// CHECK-NOT: call void @llvm.dbg.declare(metadata i32** %gbl_dynamic_int.addr
+// CHECK-NOT: call void @llvm.dbg.declare(metadata i32** %gbl_static_int.addr
+
+extern int printf(const char *, ...);
+extern void omp_set_num_threads(int);
+extern int omp_get_num_threads(void);
+extern int omp_get_thread_num(void);
+
+int gbl_dynamic_int;
+__thread int gbl_static_int;
+
+#pragma omp threadprivate(gbl_dynamic_int)
+
+int main() {
+  int nt = 0;
+  int offset = 10;
+  gbl_dynamic_int = 55;
+  gbl_static_int = 77;
+
+  omp_set_num_threads(4);
+#pragma omp parallel copyin(gbl_dynamic_int, gbl_static_int)
+  {
+    int data;
+    int tid;
+    nt = omp_get_num_threads();
+    tid = omp_get_thread_num();
+    data = gbl_dynamic_int + gbl_static_int;
+    gbl_dynamic_int += 10;
+    gbl_static_int += 20;
+#pragma omp barrier
+    if (tid == 0)
+      printf("In parallel region total threads = %d, thread id = %d data=%d gbl_dyn_addr = %p, gbl_static_addr = %p\n",
+             nt, tid, data, &gbl_dynamic_int, &gbl_static_int);
+    if (tid == 1)
+      printf("In parallel region total threads = %d, thread id = %d data=%d gbl_dyn_addr = %p, gbl_static_addr = %p\n",
+             nt, tid, data, &gbl_dynamic_int, &gbl_static_int);
+    if (tid == 2)
+      printf("In parallel region total threads = %d, thread id = %d data=%d gbl_dyn_addr = %p, gbl_static_addr = %p\n",
+             nt, tid, data, &gbl_dynamic_int, &gbl_static_int);
+    if (tid == 3)
+      printf("In parallel region total threads = %d, thread id = %d data=%d gbl_dyn_addr = %p, gbl_static_addr = %p\n",
+             nt, tid, data, &gbl_dynamic_int, &gbl_static_int);
+  }
+
+  return 0;
+}
Index: clang/lib/CodeGen/CGStmtOpenMP.cpp
===================================================================
--- clang/lib/CodeGen/CGStmtOpenMP.cpp
+++ clang/lib/CodeGen/CGStmtOpenMP.cpp
@@ -481,7 +481,11 @@
     if (ArgType->isVariablyModifiedType())
       ArgType = getCanonicalParamType(Ctx, ArgType);
     VarDecl *Arg;
-    if (DebugFunctionDecl && (CapVar || I->capturesThis())) {
+    if (CapVar && (CapVar->getTLSKind() != clang::VarDecl::TLS_None)) {
+      Arg = ImplicitParamDecl::Create(Ctx, /*DC=*/nullptr, FD->getLocation(),
+                                      II, ArgType,
+                                      ImplicitParamDecl::ThreadPrivateVar);
+    } else if (DebugFunctionDecl && (CapVar || I->capturesThis())) {
       Arg = ParmVarDecl::Create(
           Ctx, DebugFunctionDecl,
           CapVar ? CapVar->getBeginLoc() : FD->getBeginLoc(),
Index: clang/lib/CodeGen/CGDecl.cpp
===================================================================
--- clang/lib/CodeGen/CGDecl.cpp
+++ clang/lib/CodeGen/CGDecl.cpp
@@ -2432,6 +2432,7 @@
 /// for the specified parameter and set up LocalDeclMap.
 void CodeGenFunction::EmitParmDecl(const VarDecl &D, ParamValue Arg,
                                    unsigned ArgNo) {
+  bool NoDebugInfo = false;
   // FIXME: Why isn't ImplicitParamDecl a ParmVarDecl?
   assert((isa<ParmVarDecl>(D) || isa<ImplicitParamDecl>(D)) &&
          "Invalid argument to EmitParmDecl");
@@ -2451,6 +2452,10 @@
       setBlockContextParameter(IPD, ArgNo, V);
       return;
     }
+    // Suppressing debug info for ThreadPrivateVar parameters, else it hides
+    // debug info of TLS variables.
+    NoDebugInfo =
+        (IPD->getParameterKind() == ImplicitParamDecl::ThreadPrivateVar);
   }
 
   Address DeclPtr = Address::invalid();
@@ -2581,7 +2586,8 @@
 
   // Emit debug info for param declarations in non-thunk functions.
   if (CGDebugInfo *DI = getDebugInfo()) {
-    if (CGM.getCodeGenOpts().hasReducedDebugInfo() && !CurFuncIsThunk) {
+    if (CGM.getCodeGenOpts().hasReducedDebugInfo() && !CurFuncIsThunk &&
+        !NoDebugInfo) {
       llvm::DILocalVariable *DILocalVar = DI->EmitDeclareOfArgVariable(
           &D, AllocaPtr.getPointer(), ArgNo, Builder);
       if (const auto *Var = dyn_cast_or_null<ParmVarDecl>(&D))
Index: clang/include/clang/AST/Decl.h
===================================================================
--- clang/include/clang/AST/Decl.h
+++ clang/include/clang/AST/Decl.h
@@ -1619,6 +1619,9 @@
     /// Parameter for captured context
     CapturedContext,
 
+    /// Parameter for Thread private variable
+    ThreadPrivateVar,
+
     /// Other implicit parameter
     Other,
   };
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to