[clang] 5ec6ea3 - [clang][OpenMP][DebugInfo] Mark OpenMP generated functions as artificial
Author: Alok Kumar Sharma Date: 2022-08-02T21:24:46+05:30 New Revision: 5ec6ea3dfded028de775eb165ce0bae6f1e6c2bf URL: https://github.com/llvm/llvm-project/commit/5ec6ea3dfded028de775eb165ce0bae6f1e6c2bf DIFF: https://github.com/llvm/llvm-project/commit/5ec6ea3dfded028de775eb165ce0bae6f1e6c2bf.diff LOG: [clang][OpenMP][DebugInfo] Mark OpenMP generated functions as artificial The Clang compiler generates internal functions for OpenMP. Current patch marks these functions as artificial. Reviewed By: aprantl Differential Revision: https://reviews.llvm.org/D111521 Added: clang/test/OpenMP/outlined_artificial.c Modified: clang/lib/CodeGen/CGDebugInfo.cpp Removed: diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index 6821fc97e5047..522ed7ae8b144 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -4097,8 +4097,12 @@ void CGDebugInfo::emitFunctionStart(GlobalDecl GD, SourceLocation Loc, if (Name.startswith("\01")) Name = Name.substr(1); + assert((!D || !isa(D) || + GD.getDynamicInitKind() != DynamicInitKind::NoStub) && + "Unexpected DynamicInitKind !"); + if (!HasDecl || D->isImplicit() || D->hasAttr() || - (isa(D) && GD.getDynamicInitKind() != DynamicInitKind::NoStub)) { + isa(D) || isa(D)) { Flags |= llvm::DINode::FlagArtificial; // Artificial functions should not silently reuse CurLoc. CurLoc = SourceLocation(); diff --git a/clang/test/OpenMP/outlined_artificial.c b/clang/test/OpenMP/outlined_artificial.c new file mode 100644 index 0..4c997ef2e68f5 --- /dev/null +++ b/clang/test/OpenMP/outlined_artificial.c @@ -0,0 +1,67 @@ +// This testcase checks emission of DIFlagArtificial flag for outlined +// subroutines generated by compiler. + +// 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 + +#if defined(_WIN32) +#define __KAI_KMPC_CONVENTION __cdecl +#else +#define __KAI_KMPC_CONVENTION +#endif + +extern int printf(const char *, ...); +extern void __KAI_KMPC_CONVENTION omp_set_num_threads(int); +extern int __KAI_KMPC_CONVENTION omp_get_thread_num(void); + +#define N 10 + +float f[10]; +void foo_simd(int low, int up) { + for (int i = low; i < up; ++i) { +f[i] = 0.0; +#pragma omp ordered simd +f[i] = 1.0; + } +} + +int main() { + int arr[10]; + int i; + omp_set_num_threads(2); +#pragma omp parallel +#pragma omp single +#pragma omp taskloop num_tasks(10) + for (i = 0; i < N; i++) { +arr[i] = i * i; + } + + for (int j = 0; j < N; j++) { +printf("%d\n", arr[j]); + } + return 0; +} + +// foo_simd is not artificial. +// CHECK-DAG: !DISubprogram(name: "foo_simd" +// CHECK-DAG-SAME: flags: DIFlagPrototyped, + +// CHECK-DAG: !DISubprogram(name: "__captured_stmt_debug__" +// CHECK-DAG-SAME: flags: DIFlagArtificial + +// CHECK-DAG: !DISubprogram(name: "__captured_stmt" +// CHECK-DAG-SAME: flags: DIFlagArtificial + +// CHECK-DAG: !DISubprogram(name: ".omp_outlined._debug__" +// CHECK-DAG-SAME: flags: DIFlagArtificial + +// CHECK-DAG: !DISubprogram(linkageName: ".omp_task_entry." +// CHECK-DAG-SAME: flags: DIFlagArtificial + +// CHECK-DAG: !DISubprogram(name: ".omp_outlined." +// CHECK-DAG-SAME: flags: DIFlagArtificial + +// CHECK-DAG: !DISubprogram(name: ".omp_outlined..1" +// CHECK-DAG-SAME: flags: DIFlagArtificial ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] a48300a - [clang][OpenMP][DebugInfo] Debug support for TLS variables present in OpenMP consruct
Author: Alok Kumar Sharma Date: 2022-04-23T12:29:32+05:30 New Revision: a48300aee570f8eea4ec0b03e2d176aab648afb0 URL: https://github.com/llvm/llvm-project/commit/a48300aee570f8eea4ec0b03e2d176aab648afb0 DIFF: https://github.com/llvm/llvm-project/commit/a48300aee570f8eea4ec0b03e2d176aab648afb0.diff LOG: [clang][OpenMP][DebugInfo] Debug support for TLS variables present in OpenMP consruct 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. User never gets the actual TLS variable when inquires it, instead gets the artificial parameter. Current patch suppresses the debug info for such artificial parameter to enable correct debugging of TLS variables. Reviewed By: aprantl Differential Revision: https://reviews.llvm.org/D123787 Added: clang/test/OpenMP/debug_threadprivate_copyin.c Modified: clang/include/clang/AST/Decl.h clang/lib/CodeGen/CGDecl.cpp clang/lib/CodeGen/CGStmtOpenMP.cpp Removed: diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index f93008cdd322d..04101c3218d71 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -1633,6 +1633,9 @@ class ImplicitParamDecl : public VarDecl { /// Parameter for captured context CapturedContext, +/// Parameter for Thread private variable +ThreadPrivateVar, + /// Other implicit parameter Other, }; diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp index e47450f2ba8fe..0f16c7f50a003 100644 --- a/clang/lib/CodeGen/CGDecl.cpp +++ b/clang/lib/CodeGen/CGDecl.cpp @@ -2442,6 +2442,7 @@ namespace { /// 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(D) || isa(D)) && "Invalid argument to EmitParmDecl"); @@ -2461,6 +2462,10 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, ParamValue Arg, 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(); @@ -2591,7 +2596,8 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, ParamValue Arg, // 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(&D)) diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index a249ef9d58d97..7c0001594a33e 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -481,7 +481,11 @@ static llvm::Function *emitOutlinedFunctionPrologue( 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(), diff --git a/clang/test/OpenMP/debug_threadprivate_copyin.c b/clang/test/OpenMP/debug_threadprivate_copyin.c new file mode 100644 index 0..bb0b76d5242a4 --- /dev/null +++ b/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
[clang] 36cb747 - [clang][OpenMP][DebugInfo] Debug support for private variables inside an OpenMP task construct
Author: Alok Kumar Sharma Date: 2021-11-25T19:55:22+05:30 New Revision: 36cb7477d1d43de1d97a4c2b4ba0eb5ae29cbafd URL: https://github.com/llvm/llvm-project/commit/36cb7477d1d43de1d97a4c2b4ba0eb5ae29cbafd DIFF: https://github.com/llvm/llvm-project/commit/36cb7477d1d43de1d97a4c2b4ba0eb5ae29cbafd.diff LOG: [clang][OpenMP][DebugInfo] Debug support for private variables inside an OpenMP task construct Currently variables appearing inside private/firstprivate/lastprivate clause of openmp task construct are not visible inside lldb debugger. This is because compiler does not generate debug info for it. Please consider the testcase debug_private.c attached with patch. ``` 28 #pragma omp task shared(res) private(priv1, priv2) firstprivate(fpriv) 29 { 30 priv1 = n; 31 priv2 = n + 2; 32 printf("Task n=%d,priv1=%d,priv2=%d,fpriv=%d\n",n,priv1,priv2,fpriv); 33 -> 34 res = priv1 + priv2 + fpriv + foo(n - 1); 35 } 36 #pragma omp taskwait 37 return res; (lldb) p priv1 error: :1:1: use of undeclared identifier 'priv1' priv1 ^ (lldb) p priv2 error: :1:1: use of undeclared identifier 'priv2' priv2 ^ (lldb) p fpriv error: :1:1: use of undeclared identifier 'fpriv' fpriv ^ ``` After the current patch, lldb is able to show the variables ``` (lldb) p priv1 (int) $0 = 10 (lldb) p priv2 (int) $1 = 12 (lldb) p fpriv (int) $2 = 14 ``` Reviewed By: djtodoro Differential Revision: https://reviews.llvm.org/D114504 Added: clang/test/OpenMP/debug_private.c Modified: clang/lib/CodeGen/CGStmtOpenMP.cpp Removed: diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index 4f14459e4d285..f6853a22cd361 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -4510,6 +4510,9 @@ void CodeGenFunction::EmitOMPTaskBasedDirective( Address Replacement(CGF.Builder.CreateLoad(Pair.second), CGF.getContext().getDeclAlign(Pair.first)); Scope.addPrivate(Pair.first, [Replacement]() { return Replacement; }); +if (auto *DI = CGF.getDebugInfo()) + DI->EmitDeclareOfAutoVariable(Pair.first, Pair.second.getPointer(), +CGF.Builder, /*UsePointerValue*/ true); } // Adjust mapping for internal locals by mapping actual memory instead of // a pointer to this memory. diff --git a/clang/test/OpenMP/debug_private.c b/clang/test/OpenMP/debug_private.c new file mode 100644 index 0..a68e1d1be7526 --- /dev/null +++ b/clang/test/OpenMP/debug_private.c @@ -0,0 +1,45 @@ +// This testcase checks emission of debug info for variables inside +// private/firstprivate/lastprivate. + +// 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 i32 @.omp_task_entry. + +// CHECK: call void @llvm.dbg.declare(metadata i32** %.priv.ptr.addr.i, metadata [[PRIV1:![0-9]+]], metadata !DIExpression(DW_OP_deref)) +// CHECK: call void @llvm.dbg.declare(metadata i32** %.priv.ptr.addr1.i, metadata [[PRIV2:![0-9]+]], metadata !DIExpression(DW_OP_deref)) +// CHECK: call void @llvm.dbg.declare(metadata i32** %.firstpriv.ptr.addr.i, metadata [[FPRIV:![0-9]+]], metadata !DIExpression(DW_OP_deref)) + +// CHECK: [[PRIV1]] = !DILocalVariable(name: "priv1" +// CHECK: [[PRIV2]] = !DILocalVariable(name: "priv2" +// CHECK: [[FPRIV]] = !DILocalVariable(name: "fpriv" + +extern int printf(const char *, ...); + +int foo(int n) { + int res, priv1, priv2, fpriv; + fpriv = n + 4; + + if (n < 2) +return n; + else { +#pragma omp task shared(res) private(priv1, priv2) firstprivate(fpriv) +{ + priv1 = n; + priv2 = n + 2; + printf("Task n=%d,priv1=%d,priv2=%d,fpriv=%d\n", n, priv1, priv2, fpriv); + + res = priv1 + priv2 + fpriv + foo(n - 1); +} +#pragma omp taskwait +return res; + } +} + +int main() { + int n = 10; + printf("foo(%d) = %d\n", n, foo(n)); + return 0; +} ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] 5eb2718 - [clang][OpenMP][DebugInfo] Debug support for variables in shared clause of OpenMP task construct
Author: Alok Kumar Sharma Date: 2021-12-22T20:04:21+05:30 New Revision: 5eb271880c8fc59835797806ac44f736eaf3ddbd URL: https://github.com/llvm/llvm-project/commit/5eb271880c8fc59835797806ac44f736eaf3ddbd DIFF: https://github.com/llvm/llvm-project/commit/5eb271880c8fc59835797806ac44f736eaf3ddbd.diff LOG: [clang][OpenMP][DebugInfo] Debug support for variables in shared clause of OpenMP task construct Currently variables appearing inside shared clause of OpenMP task construct are not visible inside lldb debugger. After the current patch, lldb is able to show the variable ``` * thread #1, name = 'a.out', stop reason = breakpoint 1.1 frame #0: 0x00400934 a.out`.omp_task_entry. [inlined] .omp_outlined.(.global_tid.=0, .part_id.=0x0071f0d0, .privates.=0x0071f0e8, .copy_fn.=(a.out`.omp_task_privates_map. at testshared.cxx:8), .task_t.=0x0071f0c0, __context=0x0071f0f0) at testshared.cxx:10:34 7 else { 8#pragma omp task shared(svar) firstprivate(n) 9{ -> 10 printf("Task svar = %d\n", svar); 11 printf("Task n = %d\n", n); 12 svar = fib(n - 1); 13 } (lldb) p svar (int) $0 = 9 ``` Reviewed By: djtodoro Differential Revision: https://reviews.llvm.org/D115510 Added: clang/test/OpenMP/debug_task_shared.c Modified: clang/lib/CodeGen/CGStmtOpenMP.cpp clang/lib/CodeGen/CodeGenFunction.h Removed: diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index 2509de486671a..5677fce355d55 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -24,10 +24,13 @@ #include "clang/AST/StmtVisitor.h" #include "clang/Basic/OpenMPKinds.h" #include "clang/Basic/PrettyStackTrace.h" +#include "llvm/BinaryFormat/Dwarf.h" #include "llvm/Frontend/OpenMP/OMPConstants.h" #include "llvm/Frontend/OpenMP/OMPIRBuilder.h" #include "llvm/IR/Constants.h" +#include "llvm/IR/DebugInfoMetadata.h" #include "llvm/IR/Instructions.h" +#include "llvm/IR/Metadata.h" #include "llvm/Support/AtomicOrdering.h" using namespace clang; using namespace CodeGen; @@ -4431,6 +4434,53 @@ void CodeGenFunction::EmitOMPTaskBasedDirective( UntiedLocalVars; // Set proper addresses for generated private copies. OMPPrivateScope Scope(CGF); +// Generate debug info for variables present in shared clause. +if (auto *DI = CGF.getDebugInfo()) { + llvm::SmallDenseMap CaptureFields = + CGF.CapturedStmtInfo->getCaptureFields(); + llvm::Value *ContextValue = CGF.CapturedStmtInfo->getContextValue(); + if (CaptureFields.size() && ContextValue) { +unsigned CharWidth = CGF.getContext().getCharWidth(); +// The shared variables are packed together as members of structure. +// So the address of each shared variable can be computed by adding +// offset of it (within record) to the base address of record. For each +// shared variable, debug intrinsic llvm.dbg.declare is generated with +// appropriate expressions (DIExpression). +// Ex: +// %12 = load %struct.anon*, %struct.anon** %__context.addr.i +// call void @llvm.dbg.declare(metadata %struct.anon* %12, +//metadata !svar1, +//metadata !DIExpression(DW_OP_deref)) +// call void @llvm.dbg.declare(metadata %struct.anon* %12, +//metadata !svar2, +//metadata !DIExpression(DW_OP_plus_uconst, 8, DW_OP_deref)) +for (auto It = CaptureFields.begin(); It != CaptureFields.end(); ++It) { + const VarDecl *SharedVar = It->first; + RecordDecl *CaptureRecord = It->second->getParent(); + const ASTRecordLayout &Layout = + CGF.getContext().getASTRecordLayout(CaptureRecord); + unsigned Offset = + Layout.getFieldOffset(It->second->getFieldIndex()) / CharWidth; + (void)DI->EmitDeclareOfAutoVariable(SharedVar, ContextValue, + CGF.Builder, false); + llvm::Instruction &Last = CGF.Builder.GetInsertBlock()->back(); + // Get the call dbg.declare instruction we just created and update + // its DIExpression to add offset to base address. + if (auto DDI = dyn_cast(&Last)) { +SmallVector Ops; +// Add offset to the base address if non zero. +if (Offset) { + Ops.push_back(llvm::dwarf::DW_OP_plus_uconst); + Ops.push_back(Offset); +} +Ops.push_back(llvm::dwarf::DW_OP_deref); +auto &Ctx = DDI->getContext(); +llvm::DIExpression *DIExpr = llvm::DIExpression::get(Ctx, Ops); +Last.setOperand(2, llvm::MetadataAsValue::get(Ctx, DIExpr)); + } +} + } +} llvm::SmallVector
[clang] [OpenMP] [Debug] Debug support for work sharing iterator variable (PR #122047)
alokkrsharma wrote: > Maybe it fixes debug info, but definitely breaks some of the OpenMP support Thanks for your comment. Though I intend to delete only unused instructions but it is possible that I have overlooked something. Would you please help me with some example, I will improve the fix with concerns addressed. https://github.com/llvm/llvm-project/pull/122047 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [OpenMP] [Debug] Debug support for work sharing iterator variable (PR #122047)
alokkrsharma wrote: > The fix doesn't look right to me... Thanks for your comment [shiltian](https://github.com/shiltian). I would love to address your concern and improve the patch. Please help me with the example. https://github.com/llvm/llvm-project/pull/122047 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [OpenMP] [Debug] Debug support for work sharing iterator variable (PR #122047)
https://github.com/alokkrsharma edited https://github.com/llvm/llvm-project/pull/122047 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits