diff --git a/gcc/testsuite/gnat.dg/opt94.adb b/gcc/testsuite/gnat.dg/opt94.adb new file mode 100644 index 0000000000000000000000000000000000000000..547bef3a918552cd799776a98c592c47f98fc684 --- /dev/null +++ b/gcc/testsuite/gnat.dg/opt94.adb @@ -0,0 +1,17 @@ +-- { dg-do compile } +-- { dg-options "-O -gnatn -fdump-tree-optimized" } + +with Opt94_Pkg; use Opt94_Pkg; + +function Opt94 (S : String) return Integer is + A : constant String := Get; + +begin + if Valid_Result (A) then + return Result (A); + else + return -1; + end if; +end; + +-- { dg-final { scan-tree-dump-times "worker" 1 "optimized" } } diff --git a/gcc/testsuite/gnat.dg/opt94_pkg.adb b/gcc/testsuite/gnat.dg/opt94_pkg.adb new file mode 100644 index 0000000000000000000000000000000000000000..670291712fb8cbee24771bd15c8ccab40f1d333b --- /dev/null +++ b/gcc/testsuite/gnat.dg/opt94_pkg.adb @@ -0,0 +1,31 @@ +package body Opt94_Pkg is + + function Worker (S : String) return Integer; + pragma Pure_Function (Worker); + + function Valid_Result (S : String) return Boolean is + begin + return Worker (S) > 0; + end; + + function Result (S : String) return Integer is + R : constant Integer := Worker (S); + begin + if R > 0 then + return R; + else + raise Program_Error; + end if; + end; + + function Worker (S : String) return Integer is + begin + return Character'Pos (S (S'First)); + end; + + function Get return String is + begin + return ""; + end; + +end Opt94_Pkg; diff --git a/gcc/testsuite/gnat.dg/opt94_pkg.ads b/gcc/testsuite/gnat.dg/opt94_pkg.ads new file mode 100644 index 0000000000000000000000000000000000000000..16e34338d55258857eab2d79b170b37d93c56468 --- /dev/null +++ b/gcc/testsuite/gnat.dg/opt94_pkg.ads @@ -0,0 +1,11 @@ +package Opt94_Pkg is + + function Valid_Result (S : String) return Boolean; + pragma Inline (Valid_Result); + + function Result (S : String) return Integer; + pragma Inline (Result); + + function Get return String; + +end Opt94_Pkg; diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index 1dcb31c02676d36fb3a6b074f1a00d20a5e13a94..49a5850f41048154dafbad3b762c4f6b2ad13c15 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -152,30 +152,6 @@ insert_decl_map (copy_body_data *id, tree key, tree value) id->decl_map->put (value, value); } -/* Insert a tree->tree mapping for ID. This is only used for - variables. */ - -static void -insert_debug_decl_map (copy_body_data *id, tree key, tree value) -{ - if (!gimple_in_ssa_p (id->src_cfun)) - return; - - if (!opt_for_fn (id->dst_fn, flag_var_tracking_assignments)) - return; - - if (!target_for_debug_bind (key)) - return; - - gcc_assert (TREE_CODE (key) == PARM_DECL); - gcc_assert (VAR_P (value)); - - if (!id->debug_map) - id->debug_map = new hash_map<tree, tree>; - - id->debug_map->put (key, value); -} - /* If nonzero, we're remapping the contents of inlined debug statements. If negative, an error has occurred, such as a reference to a variable that isn't available in the inlined @@ -3190,7 +3166,8 @@ copy_debug_stmt (gdebug *stmt, copy_body_data *id) else gcc_unreachable (); - if (TREE_CODE (t) == PARM_DECL && id->debug_map + if (TREE_CODE (t) == PARM_DECL + && id->debug_map && (n = id->debug_map->get (t))) { gcc_assert (VAR_P (*n)); @@ -3460,16 +3437,18 @@ setup_one_parameter (copy_body_data *id, tree p, tree value, tree fn, value. */ if (TREE_READONLY (p) && !TREE_ADDRESSABLE (p) - && value && !TREE_SIDE_EFFECTS (value) + && value + && !TREE_SIDE_EFFECTS (value) && !def) { - /* We may produce non-gimple trees by adding NOPs or introduce - invalid sharing when operand is not really constant. - It is not big deal to prohibit constant propagation here as - we will constant propagate in DOM1 pass anyway. */ - if (is_gimple_min_invariant (value) - && useless_type_conversion_p (TREE_TYPE (p), - TREE_TYPE (value)) + /* We may produce non-gimple trees by adding NOPs or introduce invalid + sharing when the value is not constant or DECL. And we need to make + sure that it cannot be modified from another path in the callee. */ + if ((is_gimple_min_invariant (value) + || (DECL_P (value) && TREE_READONLY (value)) + || (auto_var_in_fn_p (value, id->src_fn) + && !TREE_ADDRESSABLE (value))) + && useless_type_conversion_p (TREE_TYPE (p), TREE_TYPE (value)) /* We have to be very careful about ADDR_EXPR. Make sure the base variable isn't a local variable of the inlined function, e.g., when doing recursive inlining, direct or @@ -3478,7 +3457,9 @@ setup_one_parameter (copy_body_data *id, tree p, tree value, tree fn, && ! self_inlining_addr_expr (value, fn)) { insert_decl_map (id, p, value); - insert_debug_decl_map (id, p, var); + if (!id->debug_map) + id->debug_map = new hash_map<tree, tree>; + id->debug_map->put (p, var); return insert_init_debug_bind (id, bb, var, value, NULL); } } @@ -5128,8 +5109,13 @@ expand_call_inline (basic_block bb, gimple *stmt, copy_body_data *id, for (tree p = DECL_ARGUMENTS (id->src_fn); p; p = DECL_CHAIN (p)) if (!TREE_THIS_VOLATILE (p)) { + /* The value associated with P is a local temporary only if + there is no value associated with P in the debug map. */ tree *varp = id->decl_map->get (p); - if (varp && VAR_P (*varp) && !is_gimple_reg (*varp)) + if (varp + && VAR_P (*varp) + && !is_gimple_reg (*varp) + && !(id->debug_map && id->debug_map->get (p))) { tree clobber = build_clobber (TREE_TYPE (*varp)); gimple *clobber_stmt; diff --git a/gcc/tree-inline.h b/gcc/tree-inline.h index f20cff31f0954905395c56da5969f70355bafb8b..ec0e82fe865e41c582cd85ffca82bcc2288e9cde 100644 --- a/gcc/tree-inline.h +++ b/gcc/tree-inline.h @@ -150,9 +150,9 @@ struct copy_body_data vec<gdebug *> debug_stmts; /* A map from local declarations in the inlined function to - equivalents in the function into which it is being inlined, where - the originals have been mapped to a value rather than to a - variable. */ + equivalents in the function into which it is being inlined, + where the originals have been mapped to a value rather than + to a variable. */ hash_map<tree, tree> *debug_map; /* A map from the inlined functions dependence info cliques to