Ahem...  I forgot to note that:

I have bootstrapped and regression tested my patch on x86_64-pc-linux-gnu.

Kevin

On Thu, 4 May 2017 17:45:51 -0700
Kevin Buettner <kev...@redhat.com> wrote:

> Consider the following OpenMP program:
> 
>     void foo (int a1) {}
> 
>     int
>     main (void)
>     {
>       static int s1 = -41;
>       int i1 = 11, i2;
> 
>       for (i2 = 1; i2 <= 2; i2++)
>         {
>           int pass = i2;
>     #pragma omp parallel num_threads (2) firstprivate (i1)
>           {
>             foo (i1);
>           }
>           foo(pass);
>         }
>       foo (s1); foo (i2);
>     }
> 
> At the moment, when debugging such a program, GDB is not able to find
> and print the values of s1, i2, and pass.
> 
> My changes to omp-low.c and omp-expand.c, in conjunction with several
> other patches, allow GDB to find and print these values.
> 
> This is the current behavior when debugging in GDB:
> 
>     (gdb) b 14
>     Breakpoint 1 at 0x400617: file ex3.c, line 14.
>     (gdb) run
>     Starting program: /mesquite2/.ironwood2/omp-tests/k/ex3-trunk
>     [Thread debugging using libthread_db enabled]
>     Using host libthread_db library "/lib64/libthread_db.so.1".
>     [New Thread 0x7ffff73ca700 (LWP 32628)]
> 
>     Thread 1 "ex3-trunk" hit Breakpoint 1, main._omp_fn.0 () at ex3.c:14
>     14              foo (i1);
>     (gdb) p s1
>     No symbol "s1" in current context.
>     (gdb) p i1
>     $1 = 11
>     (gdb) p i2
>     No symbol "i2" in current context.
>     (gdb) p pass
>     No symbol "pass" in current context.
>     (gdb) c
>     Continuing.
>     [Switching to Thread 0x7ffff73ca700 (LWP 32628)]
> 
>     Thread 2 "ex3-trunk" hit Breakpoint 1, main._omp_fn.0 () at ex3.c:14
>     14              foo (i1);
>     (gdb) p s1
>     No symbol "s1" in current context.
>     (gdb) p i1
>     $2 = 11
>     (gdb) p i2
>     No symbol "i2" in current context.
>     (gdb) p pass
>     No symbol "pass" in current context.
>     (gdb) bt
>     #0  main._omp_fn.0 () at ex3.c:14
>     #1  0x00007ffff7bc4926 in gomp_thread_start (xdata=<optimized out>)
>     at gcc/libgomp/team.c:122
>     #2  0x00007ffff799761a in start_thread () from /lib64/libpthread.so.0
>     #3  0x00007ffff76d159d in clone () from /lib64/libc.so.6
> 
> Note that GDB is unable to find s1, i2, or pass for either thread.
> 
> I show the backtrace for thread 2 because it's the more difficult case
> to handle due to the stack trace stopping at clone().  The stack frame
> for main(), which is where the variables of interest reside, is not a
> part of this stack.
> 
> When we run this example using the patches associated with this change
> along with several other patches, GDB's behavior looks like this:
> 
>     (gdb) b 14
>     Breakpoint 1 at 0x400617: file ex3.c, line 14.
>     (gdb) run
>     Starting program: /mesquite2/.ironwood2/omp-tests/k/ex3-new
>     [Thread debugging using libthread_db enabled]
>     Using host libthread_db library "/lib64/libthread_db.so.1".
>     [New Thread 0x7ffff73ca700 (LWP 32643)]
> 
>     Thread 1 "ex3-new" hit Breakpoint 1, main._omp_fn.0 () at ex3.c:14
>     14              foo (i1);
>     (gdb) p s1
>     $1 = -41
>     (gdb) p i1
>     $2 = 11
>     (gdb) p i2
>     $3 = 1
>     (gdb) p pass
>     $4 = 1
>     (gdb) c
>     Continuing.
>     [Switching to Thread 0x7ffff73ca700 (LWP 32643)]
> 
>     Thread 2 "ex3-new" hit Breakpoint 1, main._omp_fn.0 () at ex3.c:14
>     14              foo (i1);
>     (gdb) p s1
>     $5 = -41
>     (gdb) p i1
>     $6 = 11
>     (gdb) p i2
>     $7 = 1
>     (gdb) p pass
>     $8 = 1
> 
> I didn't show the stack here.  It's the same as before.  (I would,
> however, like to be able to make GDB display a unified stack.)
> 
> Note that GDB is now able to find and print values for s1, i2, and
> pass.
> 
> GCC constructs a new function for executing the parallel code.
> The debugging information entry for this function is presently
> placed at the same level as that of the function in which the
> "#pragma omp parallel" directive appeared.
> 
> This is partial output from "readelf -v" for the (non-working) example
> shown above:
> 
>  <1><2d>: Abbrev Number: 2 (DW_TAG_subprogram)
>     <2e>   DW_AT_external    : 1
>     <2e>   DW_AT_name        : (indirect string, offset: 0x80): main
>     <32>   DW_AT_decl_file   : 1
>     <33>   DW_AT_decl_line   : 4
>     <34>   DW_AT_prototyped  : 1
>     <34>   DW_AT_type        : <0x9d>
>     <38>   DW_AT_low_pc      : 0x400591
>     <40>   DW_AT_high_pc     : 0x71
>     <48>   DW_AT_frame_base  : 1 byte block: 9c         (DW_OP_call_frame_cfa)
>     <4a>   DW_AT_GNU_all_tail_call_sites: 1
>     <4a>   DW_AT_sibling     : <0x9d>
>  <2><4e>: Abbrev Number: 3 (DW_TAG_variable)
>     <4f>   DW_AT_name        : s1
>     <52>   DW_AT_decl_file   : 1
>     <53>   DW_AT_decl_line   : 6
>     <54>   DW_AT_type        : <0x9d>
>     <58>   DW_AT_location    : 9 byte block: 3 30 10 60 0 0 0 0 0       
> (DW_OP_addr: 601030)
>  ...
>  <2><7c>: Abbrev Number: 4 (DW_TAG_lexical_block)
>     <7d>   DW_AT_low_pc      : 0x4005a9
>     <85>   DW_AT_high_pc     : 0x31
>  <3><8d>: Abbrev Number: 5 (DW_TAG_variable)
>     <8e>   DW_AT_name        : (indirect string, offset: 0x55): pass
>     <92>   DW_AT_decl_file   : 1
>     <93>   DW_AT_decl_line   : 11
>     <94>   DW_AT_type        : <0x9d>
>     <98>   DW_AT_location    : 2 byte block: 91 64      (DW_OP_fbreg: -28)
>  ...
>  <1><a4>: Abbrev Number: 7 (DW_TAG_subprogram)
>     <a5>   DW_AT_name        : (indirect string, offset: 0x5a): main._omp_fn.0
>     <a9>   DW_AT_prototyped  : 1
>     <a9>   DW_AT_artificial  : 1
>     <a9>   DW_AT_low_pc      : 0x400602
>     <b1>   DW_AT_high_pc     : 0x21
>     <b9>   DW_AT_frame_base  : 1 byte block: 9c         (DW_OP_call_frame_cfa)
>     <bb>   DW_AT_GNU_all_tail_call_sites: 1
>     <bb>   DW_AT_sibling     : <0xd5>
>  <2><bf>: Abbrev Number: 8 (DW_TAG_formal_parameter)
>     <c0>   DW_AT_type        : <0xed>
>     <c4>   DW_AT_artificial  : 1
>     <c4>   DW_AT_location    : 2 byte block: 91 58      (DW_OP_fbreg: -40)
>  ...
> 
> The nesting level is indicated by the leading number in angle
> brackets.  This shows that the DW_TAG_VARIABLE DIE for s1 is nested
> within the DIE for main's DW_TAG_subprogram DIE.  Likewise, the
> lexical block corresponding to the body of the for-loop is also nested
> within main().  However, the DIES for main and main._omp_fun.0 are
> both at level 1.
> 
> With my patches for omp-low.c and omp-expand.c, the readelf -w output
> looks like this instead:
> 
>  <1><2d>: Abbrev Number: 2 (DW_TAG_subprogram)
>     <2e>   DW_AT_external    : 1
>     <2e>   DW_AT_name        : (indirect string, offset: 0x80): main
>     <32>   DW_AT_decl_file   : 1
>     <33>   DW_AT_decl_line   : 4
>     <34>   DW_AT_prototyped  : 1
>     <34>   DW_AT_type        : <0xca>
>     <38>   DW_AT_low_pc      : 0x400591
>     <40>   DW_AT_high_pc     : 0x71
>     <48>   DW_AT_frame_base  : 1 byte block: 9c         (DW_OP_call_frame_cfa)
>     <4a>   DW_AT_GNU_all_tail_call_sites: 1
>     <4a>   DW_AT_sibling     : <0xca>
>  <2><4e>: Abbrev Number: 3 (DW_TAG_variable)
>     <4f>   DW_AT_name        : s1
>     <52>   DW_AT_decl_file   : 1
>     <53>   DW_AT_decl_line   : 6
>     <54>   DW_AT_type        : <0xca>
>     <58>   DW_AT_location    : 9 byte block: 3 30 10 60 0 0 0 0 0       
> (DW_OP_addr: 601030)
>  <2><62>: Abbrev Number: 3 (DW_TAG_variable)
>     <63>   DW_AT_name        : i1
>     <66>   DW_AT_decl_file   : 1
>     <67>   DW_AT_decl_line   : 7
>     <68>   DW_AT_type        : <0xca>
>     <6c>   DW_AT_location    : 2 byte block: 91 68      (DW_OP_fbreg: -24)
>  <2><6f>: Abbrev Number: 3 (DW_TAG_variable)
>     <70>   DW_AT_name        : i2
>     <73>   DW_AT_decl_file   : 1
>     <74>   DW_AT_decl_line   : 7
>     <75>   DW_AT_type        : <0xca>
>     <79>   DW_AT_location    : 2 byte block: 91 6c      (DW_OP_fbreg: -20)
>  <2><7c>: Abbrev Number: 4 (DW_TAG_lexical_block)
>     <7d>   DW_AT_low_pc      : 0x4005a9
>     <85>   DW_AT_high_pc     : 0x31
>  <3><8d>: Abbrev Number: 5 (DW_TAG_variable)
>     <8e>   DW_AT_name        : (indirect string, offset: 0x55): pass
>     <92>   DW_AT_decl_file   : 1
>     <93>   DW_AT_decl_line   : 11
>     <94>   DW_AT_type        : <0xca>
>     <98>   DW_AT_location    : 2 byte block: 91 64      (DW_OP_fbreg: -28)
>  <3><9b>: Abbrev Number: 6 (DW_TAG_subprogram)
>     <9c>   DW_AT_name        : (indirect string, offset: 0x5a): main._omp_fn.0
>     <a0>   DW_AT_prototyped  : 1
>     <a0>   DW_AT_artificial  : 1
>     <a0>   DW_AT_low_pc      : 0x400602
>     <a8>   DW_AT_high_pc     : 0x21
>     <b0>   DW_AT_frame_base  : 1 byte block: 9c         (DW_OP_call_frame_cfa)
>     <b2>   DW_AT_GNU_all_tail_call_sites: 1
>  <4><b2>: Abbrev Number: 7 (DW_TAG_formal_parameter)
>     <b3>   DW_AT_type        : <0xe9>
>     <b7>   DW_AT_artificial  : 1
>     <b7>   DW_AT_location    : 2 byte block: 91 58      (DW_OP_fbreg: -40)
>  <4><ba>: Abbrev Number: 3 (DW_TAG_variable)
>     <bb>   DW_AT_name        : i1
>     <be>   DW_AT_decl_file   : 1
>     <bf>   DW_AT_decl_line   : 7
>     <c0>   DW_AT_type        : <0xca>
>     <c4>   DW_AT_location    : 2 byte block: 91 6c      (DW_OP_fbreg: -20)
> 
> This time, note that the lexical block for the for-loop is still nested
> within main().  The DIE for main._omp_fn.0 is nested within that lexical
> block.
> 
> This nesting enables GDB to find variables which ought to be in scope.
> 
> (Obviously, there's some extra work required for finding variables
> which reside on the stack in a different thread.  That's handled in
> patches to GDB and to libgomp.)
> 
> gcc/ChangeLog:
>     
>         * omp-low.c (create_omp_child_function): Set DECL_CONTEXT
>         of child function to that of source function.
>         * omp-expand.c (expand_parallel_call): Add child function
>         to var chain in block from which child function originated.
> 
> diff --git a/gcc/omp-expand.c b/gcc/omp-expand.c
> index 5c48b78..7029951 100644
> --- a/gcc/omp-expand.c
> +++ b/gcc/omp-expand.c
> @@ -667,6 +667,25 @@ expand_parallel_call (struct omp_region *region, 
> basic_block bb,
>    tree child_fndecl = gimple_omp_parallel_child_fn (entry_stmt);
>    t2 = build_fold_addr_expr (child_fndecl);
>  
> +  if (gimple_block (entry_stmt) != NULL_TREE
> +      && TREE_CODE (gimple_block (entry_stmt)) == BLOCK)
> +    {
> +      tree b = BLOCK_SUPERCONTEXT (gimple_block (entry_stmt));
> +
> +      /* Add child_fndecl to var chain of the supercontext of the
> +        block corresponding to entry_stmt.  This ensures that debug
> +        info for the outlined function will be emitted for the correct
> +        lexical scope.  */
> +      if (b != NULL_TREE && TREE_CODE (b) == BLOCK)
> +       {
> +         tree *tp;
> +
> +         for (tp = &BLOCK_VARS (b); *tp; tp = &DECL_CHAIN (*tp))
> +           ;
> +         *tp = child_fndecl;
> +        }
> +    }
> +
>    vec_alloc (args, 4 + vec_safe_length (ws_args));
>    args->quick_push (t2);
>    args->quick_push (t1);
> diff --git a/gcc/omp-low.c b/gcc/omp-low.c
> index 9cc2996..601d1b4 100644
> --- a/gcc/omp-low.c
> +++ b/gcc/omp-low.c
> @@ -1626,7 +1626,7 @@ create_omp_child_function (omp_context *ctx, bool 
> task_copy)
>    TREE_PUBLIC (decl) = 0;
>    DECL_UNINLINABLE (decl) = 1;
>    DECL_EXTERNAL (decl) = 0;
> -  DECL_CONTEXT (decl) = NULL_TREE;
> +  DECL_CONTEXT (decl) = ctx->cb.src_fn;
>    DECL_INITIAL (decl) = make_node (BLOCK);
>    BLOCK_SUPERCONTEXT (DECL_INITIAL (decl)) = decl;
>    if (omp_maybe_offloaded_ctx (ctx))
> 

Reply via email to