diff options
author | Thomas Koenig <tkoenig@gcc.gnu.org> | 2021-01-03 21:40:04 +0100 |
---|---|---|
committer | Thomas Koenig <tkoenig@gcc.gnu.org> | 2021-01-03 21:40:04 +0100 |
commit | afae4a55ccaa0de95ea11e5f634084db6ab2f444 (patch) | |
tree | d632cc867d10410ba9fb750523be790b86846ac4 /gcc/gimple.c | |
parent | 9d9a82ec8478ff52c7a9d61f58cd2a7b6295b5f9 (diff) | |
parent | d2eb616a0f7bea78164912aa438c29fe1ef5774a (diff) | |
download | gcc-afae4a55ccaa0de95ea11e5f634084db6ab2f444.zip gcc-afae4a55ccaa0de95ea11e5f634084db6ab2f444.tar.gz gcc-afae4a55ccaa0de95ea11e5f634084db6ab2f444.tar.bz2 |
Merge branch 'master' into devel/coarray_native
Diffstat (limited to 'gcc/gimple.c')
-rw-r--r-- | gcc/gimple.c | 108 |
1 files changed, 71 insertions, 37 deletions
diff --git a/gcc/gimple.c b/gcc/gimple.c index f19e24d..bb13458 100644 --- a/gcc/gimple.c +++ b/gcc/gimple.c @@ -46,6 +46,8 @@ along with GCC; see the file COPYING3. If not see #include "asan.h" #include "langhooks.h" #include "attr-fnspec.h" +#include "ipa-modref-tree.h" +#include "ipa-modref.h" /* All the tuples have their operand vector (if present) at the very bottom @@ -611,10 +613,6 @@ gimple_build_asm_1 (const char *string, unsigned ninputs, unsigned noutputs, gasm *p; int size = strlen (string); - /* ASMs with labels cannot have outputs. This should have been - enforced by the front end. */ - gcc_assert (nlabels == 0 || noutputs == 0); - p = as_a <gasm *> ( gimple_build_with_ops (GIMPLE_ASM, ERROR_MARK, ninputs + noutputs + nclobbers + nlabels)); @@ -1487,23 +1485,44 @@ gimple_call_flags (const gimple *stmt) /* Return the "fn spec" string for call STMT. */ -static const_tree +attr_fnspec gimple_call_fnspec (const gcall *stmt) { tree type, attr; if (gimple_call_internal_p (stmt)) - return internal_fn_fnspec (gimple_call_internal_fn (stmt)); + { + const_tree spec = internal_fn_fnspec (gimple_call_internal_fn (stmt)); + if (spec) + return spec; + else + return ""; + } type = gimple_call_fntype (stmt); - if (!type) - return NULL_TREE; - - attr = lookup_attribute ("fn spec", TYPE_ATTRIBUTES (type)); - if (!attr) - return NULL_TREE; - - return TREE_VALUE (TREE_VALUE (attr)); + if (type) + { + attr = lookup_attribute ("fn spec", TYPE_ATTRIBUTES (type)); + if (attr) + return TREE_VALUE (TREE_VALUE (attr)); + } + if (gimple_call_builtin_p (stmt, BUILT_IN_NORMAL)) + return builtin_fnspec (gimple_call_fndecl (stmt)); + tree fndecl = gimple_call_fndecl (stmt); + /* If the call is to a replaceable operator delete and results + from a delete expression as opposed to a direct call to + such operator, then we can treat it as free. */ + if (fndecl + && DECL_IS_OPERATOR_DELETE_P (fndecl) + && DECL_IS_REPLACEABLE_OPERATOR (fndecl) + && gimple_call_from_new_or_delete (stmt)) + return ".co "; + /* Similarly operator new can be treated as malloc. */ + if (fndecl + && DECL_IS_REPLACEABLE_OPERATOR_NEW_P (fndecl) + && gimple_call_from_new_or_delete (stmt)) + return "mC"; + return ""; } /* Detects argument flags for argument number ARG on call STMT. */ @@ -1511,26 +1530,46 @@ gimple_call_fnspec (const gcall *stmt) int gimple_call_arg_flags (const gcall *stmt, unsigned arg) { - const_tree attr = gimple_call_fnspec (stmt); - - if (!attr) - return 0; - + attr_fnspec fnspec = gimple_call_fnspec (stmt); int flags = 0; - attr_fnspec fnspec (attr); - if (!fnspec.arg_specified_p (arg)) - ; - else if (!fnspec.arg_used_p (arg)) - flags = EAF_UNUSED; - else + if (fnspec.known_p ()) { - if (fnspec.arg_direct_p (arg)) - flags |= EAF_DIRECT; - if (fnspec.arg_noescape_p (arg)) - flags |= EAF_NOESCAPE; - if (fnspec.arg_readonly_p (arg)) - flags |= EAF_NOCLOBBER; + if (!fnspec.arg_specified_p (arg)) + ; + else if (!fnspec.arg_used_p (arg)) + flags = EAF_UNUSED; + else + { + if (fnspec.arg_direct_p (arg)) + flags |= EAF_DIRECT; + if (fnspec.arg_noescape_p (arg)) + flags |= EAF_NOESCAPE | EAF_NODIRECTESCAPE; + if (fnspec.arg_readonly_p (arg)) + flags |= EAF_NOCLOBBER; + } + } + tree callee = gimple_call_fndecl (stmt); + if (callee) + { + cgraph_node *node = cgraph_node::get (callee); + modref_summary *summary = node ? get_modref_function_summary (node) + : NULL; + + if (summary && summary->arg_flags.length () > arg) + { + int modref_flags = summary->arg_flags[arg]; + + /* We have possibly optimized out load. Be conservative here. */ + if (!node->binds_to_current_def_p ()) + { + if ((modref_flags & EAF_UNUSED) && !(flags & EAF_UNUSED)) + modref_flags &= ~EAF_UNUSED; + if ((modref_flags & EAF_DIRECT) && !(flags & EAF_DIRECT)) + modref_flags &= ~EAF_DIRECT; + } + flags |= modref_flags; + } } return flags; } @@ -1540,15 +1579,10 @@ gimple_call_arg_flags (const gcall *stmt, unsigned arg) int gimple_call_return_flags (const gcall *stmt) { - const_tree attr; - if (gimple_call_flags (stmt) & ECF_MALLOC) return ERF_NOALIAS; - attr = gimple_call_fnspec (stmt); - if (!attr) - return 0; - attr_fnspec fnspec (attr); + attr_fnspec fnspec = gimple_call_fnspec (stmt); unsigned int arg_no; if (fnspec.returns_arg (&arg_no)) |