aboutsummaryrefslogtreecommitdiff
path: root/gcc/gimple.c
diff options
context:
space:
mode:
authorThomas Koenig <tkoenig@gcc.gnu.org>2021-01-03 21:40:04 +0100
committerThomas Koenig <tkoenig@gcc.gnu.org>2021-01-03 21:40:04 +0100
commitafae4a55ccaa0de95ea11e5f634084db6ab2f444 (patch)
treed632cc867d10410ba9fb750523be790b86846ac4 /gcc/gimple.c
parent9d9a82ec8478ff52c7a9d61f58cd2a7b6295b5f9 (diff)
parentd2eb616a0f7bea78164912aa438c29fe1ef5774a (diff)
downloadgcc-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.c108
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))