diff options
Diffstat (limited to 'gcc/tree-inline.c')
-rw-r--r-- | gcc/tree-inline.c | 98 |
1 files changed, 56 insertions, 42 deletions
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index f1470d7..3b1c459 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -811,48 +811,49 @@ remap_gimple_op_r (tree *tp, int *walk_subtrees, void *data) { /* Otherwise, just copy the node. Note that copy_tree_r already knows not to copy VAR_DECLs, etc., so this is safe. */ - if (TREE_CODE (*tp) == INDIRECT_REF) + if (TREE_CODE (*tp) == MEM_REF) { - /* Get rid of *& from inline substitutions that can happen when a - pointer argument is an ADDR_EXPR. */ + /* 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 type, new_tree, old; - - /* If we happen to get an ADDR_EXPR in n->value, strip - it manually here as we'll eventually get ADDR_EXPRs - which lie about their types pointed to. In this case - build_fold_indirect_ref wouldn't strip the - INDIRECT_REF, but we absolutely rely on that. As - fold_indirect_ref does other useful transformations, - try that first, though. */ - type = TREE_TYPE (TREE_TYPE (*n)); - new_tree = unshare_expr (*n); - old = *tp; - *tp = gimple_fold_indirect_ref (new_tree); - if (!*tp) - { - if (TREE_CODE (new_tree) == ADDR_EXPR) - { - *tp = fold_indirect_ref_1 (EXPR_LOCATION (new_tree), - type, new_tree); - /* ??? We should either assert here or build - a VIEW_CONVERT_EXPR instead of blindly leaking - incompatible types to our IL. */ - if (! *tp) - *tp = TREE_OPERAND (new_tree, 0); - } - else - { - *tp = build1 (INDIRECT_REF, type, new_tree); - TREE_THIS_VOLATILE (*tp) = TREE_THIS_VOLATILE (old); - TREE_NO_WARNING (*tp) = TREE_NO_WARNING (old); - } + tree old = *tp; + tree ptr = unshare_expr (*n); + tree tem; + if ((tem = maybe_fold_offset_to_reference (EXPR_LOCATION (*tp), + ptr, + TREE_OPERAND (*tp, 1), + TREE_TYPE (*tp))) + && TREE_THIS_VOLATILE (tem) == TREE_THIS_VOLATILE (old)) + { + tree *tem_basep = &tem; + while (handled_component_p (*tem_basep)) + tem_basep = &TREE_OPERAND (*tem_basep, 0); + if (TREE_CODE (*tem_basep) == MEM_REF) + *tem_basep + = build2 (MEM_REF, TREE_TYPE (*tem_basep), + TREE_OPERAND (*tem_basep, 0), + fold_convert (TREE_TYPE (TREE_OPERAND (*tp, 1)), + TREE_OPERAND (*tem_basep, 1))); + else + *tem_basep + = build2 (MEM_REF, TREE_TYPE (*tem_basep), + build_fold_addr_expr (*tem_basep), + build_int_cst + (TREE_TYPE (TREE_OPERAND (*tp, 1)), 0)); + *tp = tem; + } + else + { + *tp = fold_build2 (MEM_REF, TREE_TYPE (*tp), + ptr, 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; } @@ -887,7 +888,7 @@ remap_gimple_op_r (tree *tp, int *walk_subtrees, void *data) else if (TREE_CODE (*tp) == ADDR_EXPR) { /* Variable substitution need not be simple. In particular, - the INDIRECT_REF substitution above. Make sure that + the MEM_REF substitution above. Make sure that TREE_CONSTANT and friends are up-to-date. But make sure to not improperly set TREE_BLOCK on some sub-expressions. */ int invariant = is_gimple_min_invariant (*tp); @@ -895,13 +896,7 @@ remap_gimple_op_r (tree *tp, int *walk_subtrees, void *data) id->block = NULL_TREE; walk_tree (&TREE_OPERAND (*tp, 0), remap_gimple_op_r, data, NULL); id->block = block; - - /* Handle the case where we substituted an INDIRECT_REF - into the operand of the ADDR_EXPR. */ - if (TREE_CODE (TREE_OPERAND (*tp, 0)) == INDIRECT_REF) - *tp = TREE_OPERAND (TREE_OPERAND (*tp, 0), 0); - else - recompute_tree_invariant_for_addr_expr (*tp); + recompute_tree_invariant_for_addr_expr (*tp); /* If this used to be invariant, but is not any longer, then regimplification is probably needed. */ @@ -1092,6 +1087,25 @@ copy_tree_body_r (tree *tp, int *walk_subtrees, void *data) return NULL; } } + 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 tweak some special cases. */ |