diff --git a/gcc/attr-fnspec.h b/gcc/attr-fnspec.h index 1154c30e7b0..cd618cb342b 100644 --- a/gcc/attr-fnspec.h +++ b/gcc/attr-fnspec.h @@ -264,6 +264,29 @@ public: return str[1] == 'C' || str[1] == 'P'; } + /* Return EAF flags for arg I. */ + int + arg_eaf_flags (unsigned int i) + { + int flags = 0; + + if (!arg_specified_p (i)) + ; + else if (!arg_used_p (i)) + flags = EAF_UNUSED; + else + { + if (arg_direct_p (i)) + flags |= EAF_NO_INDIRECT_READ | EAF_NO_INDIRECT_ESCAPE + | EAF_NOT_RETURNED_INDIRECTLY | EAF_NO_INDIRECT_CLOBBER; + if (arg_noescape_p (i)) + flags |= EAF_NO_DIRECT_ESCAPE | EAF_NO_INDIRECT_ESCAPE; + if (arg_readonly_p (i)) + flags |= EAF_NO_DIRECT_CLOBBER | EAF_NO_INDIRECT_CLOBBER; + } + return flags; + } + /* Check validity of the string. */ void verify (); diff --git a/gcc/gimple.c b/gcc/gimple.c index 1e0fad92e15..037c6e4c827 100644 --- a/gcc/gimple.c +++ b/gcc/gimple.c @@ -1567,22 +1567,7 @@ gimple_call_arg_flags (const gcall *stmt, unsigned arg) int flags = 0; if (fnspec.known_p ()) - { - 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_NO_INDIRECT_READ | EAF_NO_INDIRECT_ESCAPE - | EAF_NOT_RETURNED_INDIRECTLY | EAF_NO_INDIRECT_CLOBBER; - if (fnspec.arg_noescape_p (arg)) - flags |= EAF_NO_DIRECT_ESCAPE | EAF_NO_INDIRECT_ESCAPE; - if (fnspec.arg_readonly_p (arg)) - flags |= EAF_NO_DIRECT_CLOBBER | EAF_NO_INDIRECT_CLOBBER; - } - } + flags = fnspec.arg_eaf_flags (arg); tree callee = gimple_call_fndecl (stmt); if (callee) { diff --git a/gcc/ipa-modref.c b/gcc/ipa-modref.c index 90985cc1326..669dbe45a3d 100644 --- a/gcc/ipa-modref.c +++ b/gcc/ipa-modref.c @@ -2476,6 +2476,14 @@ analyze_parms (modref_summary *summary, modref_summary_lto *summary_lto, /* Do the dataflow. */ eaf_analysis.propagate (); + tree attr = lookup_attribute ("fn spec", + TYPE_ATTRIBUTES + (TREE_TYPE (current_function_decl))); + attr_fnspec fnspec (attr + ? TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr))) + : ""); + + /* Store results to summaries. */ for (tree parm = DECL_ARGUMENTS (current_function_decl); parm; parm_index++, parm = TREE_CHAIN (parm)) @@ -2502,6 +2510,18 @@ analyze_parms (modref_summary *summary, modref_summary_lto *summary_lto, continue; } int flags = eaf_analysis.get_ssa_name_flags (name); + int attr_flags = fnspec.arg_eaf_flags (parm_index); + + if (dump_file && (flags | attr_flags) != flags && !(flags & EAF_UNUSED)) + { + fprintf (dump_file, + " Flags for param %i combined with fnspec flags:", + (int)parm_index); + dump_eaf_flags (dump_file, attr_flags, false); + fprintf (dump_file, " determined: "); + dump_eaf_flags (dump_file, flags, true); + } + flags |= attr_flags; /* Eliminate useless flags so we do not end up storing unnecessary summaries. */ @@ -2522,8 +2542,8 @@ analyze_parms (modref_summary *summary, modref_summary_lto *summary_lto, " Flags for param %i combined with IPA pass:", (int)parm_index); dump_eaf_flags (dump_file, past, false); - fprintf (dump_file, " local "); - dump_eaf_flags (dump_file, flags | past, true); + fprintf (dump_file, " determined: "); + dump_eaf_flags (dump_file, flags, true); } if (!(flags & EAF_UNUSED)) flags |= past; @@ -2561,7 +2581,7 @@ analyze_parms (modref_summary *summary, modref_summary_lto *summary_lto, fprintf (dump_file, " Retslot flags combined with IPA pass:"); dump_eaf_flags (dump_file, past, false); - fprintf (dump_file, " local "); + fprintf (dump_file, " determined: "); dump_eaf_flags (dump_file, flags, true); } if (!(flags & EAF_UNUSED)) @@ -2591,7 +2611,7 @@ analyze_parms (modref_summary *summary, modref_summary_lto *summary_lto, fprintf (dump_file, " Static chain flags combined with IPA pass:"); dump_eaf_flags (dump_file, past, false); - fprintf (dump_file, " local "); + fprintf (dump_file, " determined: "); dump_eaf_flags (dump_file, flags, true); } if (!(flags & EAF_UNUSED)) @@ -4503,27 +4523,7 @@ modref_merge_call_site_flags (escape_summary *sum, if (fnspec_sum) { attr_fnspec fnspec (fnspec_sum->fnspec); - int fnspec_flags = 0; - - if (fnspec.arg_specified_p (ee->arg)) - { - if (!fnspec.arg_used_p (ee->arg)) - fnspec_flags = EAF_UNUSED; - else - { - if (fnspec.arg_direct_p (ee->arg)) - fnspec_flags |= EAF_NO_INDIRECT_READ - | EAF_NO_INDIRECT_ESCAPE - | EAF_NOT_RETURNED_INDIRECTLY - | EAF_NO_INDIRECT_CLOBBER; - if (fnspec.arg_noescape_p (ee->arg)) - fnspec_flags |= EAF_NO_DIRECT_ESCAPE - | EAF_NO_INDIRECT_ESCAPE; - if (fnspec.arg_readonly_p (ee->arg)) - flags |= EAF_NO_DIRECT_CLOBBER | EAF_NO_INDIRECT_CLOBBER; - } - } - implicit_flags |= fnspec_flags; + implicit_flags |= fnspec.arg_eaf_flags (ee->arg); } if (!ee->direct) implicit_flags = deref_flags (implicit_flags, ignore_stores);