This PR shows that when SRA creates DECL_DEBUG_EXPRs with locations (and blocks) this does not work with inlining. The reason is that the inliner does not bother to copy vars used only in lhs of debug-stmts (eek) and thus ends up sharing DECL_DEBUG_EXPRs (and not re-mapping them and their location blocks). Maybe a recipie for further desaster ... (who knows). I didn't manage to get it to "properly" copy things, but basically
else if (TREE_CODE (t) == VAR_DECL && !is_global_var (t) && !pointer_map_contains (id->decl_map, t)) /* T is a non-localized variable. */; doesn't work - vars can be not in local-decls (which we all remap) due to remove-unused-locals. Thus we end up not remapping the debug var (and refer to the other functions DECL_DEBUG_EXPR). The following avoids the DECL_DEBUG_EXPR issue by clearing all location information from it (it's unused anyway). The above code should nevertheless be inspected ... I took the liberty to sync the MEM_REF code from the two nearly identical tree copying routines (eh ...), it was my first guess as to what goes wrong. Bootstrapped on x86_64-unknown-linux-gnu, testing in progress. For 4.9 we'd want a verify_no_location eventually which we can use to recurse here. Any comments about the above code? Thanks, Richard. 2013-03-08 Richard Biener <rguent...@suse.de> PR tree-optimization/56570 * tree-cfg.c (verify_expr_location_1): Verify locations for DECL_DEBUG_EXPR. * tree-sra.c (create_access_replacement): Strip locations from DECL_DEBUG_EXPRs. * tree-inline.c (copy_tree_body_r): Sync MEM_REF code from ... remap_gimple_op_r. Index: gcc/tree-cfg.c =================================================================== *** gcc/tree-cfg.c (revision 196542) --- gcc/tree-cfg.c (working copy) *************** verify_expr_location_1 (tree *tp, int *w *** 4523,4528 **** --- 4523,4537 ---- { struct pointer_set_t *blocks = (struct pointer_set_t *) data; + if (TREE_CODE (*tp) == VAR_DECL + && DECL_DEBUG_EXPR_IS_FROM (*tp)) + { + tree t = DECL_DEBUG_EXPR (*tp); + tree addr = walk_tree (&t, verify_expr_location_1, blocks, NULL); + if (addr) + return addr; + } + if (!EXPR_P (*tp)) { *walk_subtrees = false; Index: gcc/tree-sra.c =================================================================== *** gcc/tree-sra.c (revision 196541) --- gcc/tree-sra.c (working copy) *************** create_access_replacement (struct access *** 1917,1923 **** && !DECL_ARTIFICIAL (access->base)) { char *pretty_name = make_fancy_name (access->expr); ! tree debug_expr = unshare_expr (access->expr), d; bool fail = false; DECL_NAME (repl) = get_identifier (pretty_name); --- 1917,1923 ---- && !DECL_ARTIFICIAL (access->base)) { char *pretty_name = make_fancy_name (access->expr); ! tree debug_expr = unshare_expr_without_location (access->expr), d; bool fail = false; DECL_NAME (repl) = get_identifier (pretty_name); Index: gcc/tree-inline.c =================================================================== *** gcc/tree-inline.c (revision 196542) --- gcc/tree-inline.c (working copy) *************** copy_tree_body_r (tree *tp, int *walk_su *** 1092,1113 **** } else if (TREE_CODE (*tp) == MEM_REF) { ! /* We need to re-canonicalize MEM_REFs from inline substitutions ! that can happen when a pointer argument is an ADDR_EXPR. */ ! tree decl = TREE_OPERAND (*tp, 0); ! tree *n; ! n = (tree *) pointer_map_contains (id->decl_map, decl); ! if (n) ! { ! tree old = *tp; ! *tp = fold_build2 (MEM_REF, TREE_TYPE (*tp), ! unshare_expr (*n), TREE_OPERAND (*tp, 1)); ! TREE_THIS_VOLATILE (*tp) = TREE_THIS_VOLATILE (old); ! TREE_NO_WARNING (*tp) = TREE_NO_WARNING (old); ! *walk_subtrees = 0; ! return NULL; ! } } /* Here is the "usual case". Copy this tree node, and then --- 1092,1113 ---- } else if (TREE_CODE (*tp) == MEM_REF) { ! tree ptr = TREE_OPERAND (*tp, 0); ! tree type = remap_type (TREE_TYPE (*tp), id); ! tree old = *tp; ! /* We need to re-canonicalize MEM_REFs from inline substitutions ! that can happen when a pointer argument is an ADDR_EXPR. ! Recurse here manually to allow that. */ ! walk_tree (&ptr, copy_tree_body_r, data, NULL); ! *tp = fold_build2 (MEM_REF, type, ! ptr, TREE_OPERAND (*tp, 1)); ! TREE_THIS_NOTRAP (*tp) = TREE_THIS_NOTRAP (old); ! TREE_THIS_VOLATILE (*tp) = TREE_THIS_VOLATILE (old); ! TREE_SIDE_EFFECTS (*tp) = TREE_SIDE_EFFECTS (old); ! TREE_NO_WARNING (*tp) = TREE_NO_WARNING (old); ! *walk_subtrees = 0; ! return NULL; } /* Here is the "usual case". Copy this tree node, and then