Hi!

With the PR54519 patch I've just posted, I've noticed, I've noticed on the
same testcase from yesterday's IRC:
static inline void foo (int x, int y) { asm volatile ("nop"); }
static inline void bar (int z) { foo (z, 0); foo (z, 1); }
int main ()
{
  bar (0);
  bar (1);
  return 0;
}
that while I can print x and y just fine, if I do bt, x, y and z printed
in the backtrace are all optimized out.
The problem is that first tree versioning for foo.isra.* or bar.isra.*
deposits the optimized away parameters as VAR_DECLs into the DECL_INITIAL
block (which is fine), but then during inlining they end up in the remapped
block of DECL_INITIAL, not the new block added above it into which inliner
puts parameters.  So in the debug info we have
DW_TAG_inlined_subroutine
  DW_TAG_formal_parameter for non-optimized away parameters
  DW_TAG_lexical_block
    DW_TAG_formal_parameter for optimized away parameters
and the debugger (expectably) looks only at DW_TAG_inlined_subroutine
DIE's immediate children for the formal parameters to print during
backtrace.
Fixed up by moving the VAR_DECLs for parameters optimized away by versioning
to BLOCK_SUPERCONTEXT during inlining, at that point we know both of the
blocks have the same scope, and if the original DECL_INITIAL doesn't contain
any other vars, we can actually end up with shorter/more correct debug info
as well as memory savings due to being able to GC the remapped DECL_INITIAL
block.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2012-10-03  Jakub Jelinek  <ja...@redhat.com>

        * tree-inline.c (expand_call_inline): Move VAR_DECLs with
        PARM_DECL origins from remapped DECL_INITIAL's BLOCK_VARS
        into id->block's BLOCK_VARS.

--- gcc/tree-inline.c.jj        2012-10-02 17:43:13.000000000 +0200
+++ gcc/tree-inline.c   2012-10-02 19:43:52.576382413 +0200
@@ -3946,7 +3946,29 @@ expand_call_inline (basic_block bb, gimp
   initialize_inlined_parameters (id, stmt, fn, bb);
 
   if (DECL_INITIAL (fn))
-    prepend_lexical_block (id->block, remap_blocks (DECL_INITIAL (fn), id));
+    {
+      tree *var;
+
+      prepend_lexical_block (id->block, remap_blocks (DECL_INITIAL (fn), id));
+      gcc_checking_assert (BLOCK_SUBBLOCKS (id->block)
+                          && (BLOCK_CHAIN (BLOCK_SUBBLOCKS (id->block))
+                              == NULL_TREE));
+      /* Move vars for PARM_DECLs from DECL_INITIAL block to id->block,
+        otherwise DW_TAG_formal_parameter will not be children of
+        DW_TAG_inlined_subroutine, but of a DW_TAG_lexical_block
+        under it.  The parameters can be then evaluated in the debugger,
+        but don't show in backtraces.  */
+      for (var = &BLOCK_VARS (BLOCK_SUBBLOCKS (id->block)); *var; )
+       if (TREE_CODE (DECL_ORIGIN (*var)) == PARM_DECL)
+         {
+           tree v = *var;
+           *var = TREE_CHAIN (v);
+           TREE_CHAIN (v) = BLOCK_VARS (id->block);
+           BLOCK_VARS (id->block) = v;
+         }
+       else
+         var = &TREE_CHAIN (*var);
+    }
 
   /* Return statements in the function body will be replaced by jumps
      to the RET_LABEL.  */


        Jakub

Reply via email to