1/* Search for references that a functions loads or stores.
2   Copyright (C) 2019-2022 Free Software Foundation, Inc.
3
4This file is part of GCC.
5
6GCC is free software; you can redistribute it and/or modify it under
7the terms of the GNU General Public License as published by the Free
8Software Foundation; either version 3, or (at your option) any later
9version.
10
11GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12WARRANTY; without even the implied warranty of MERCHANTABILITY or
13FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14for more details.
15
16You should have received a copy of the GNU General Public License
17along with GCC; see the file COPYING3.  If not see
18<http://www.gnu.org/licenses/>.  */
19
20#ifndef IPA_MODREF_H
21#define IPA_MODREF_H
22
23typedef modref_tree <alias_set_type> modref_records;
24typedef unsigned short eaf_flags_t;
25
26/* Single function summary.  */
27
28struct GTY(()) modref_summary
29{
30  /* Load and stores in function (transitively closed to all callees)  */
31  modref_records *loads;
32  modref_records *stores;
33  auto_vec<modref_access_node> GTY((skip)) kills;
34  auto_vec<eaf_flags_t> GTY((skip)) arg_flags;
35
36  eaf_flags_t retslot_flags;
37  eaf_flags_t static_chain_flags;
38
39  unsigned writes_errno : 1;
40  /* Side effects does not include memory loads and stores which are
41     expressed using loads, stores and calls_interposable fields.  */
42  unsigned side_effects : 1;
43  /* If true function can not be CSE optimized because it may behave
44     differently even if invoked with same inputs.  */
45  unsigned nondeterministic : 1;
46  /* IF true the function may read any reachable memory but not use
47     it for anything useful.  This may happen i.e. when interposing
48     function with optimized out conditional with unoptimized one.
49
50     In this situation the loads summary is not useful for DSE but
51     it is still useful for CSE.  */
52  unsigned calls_interposable : 1;
53
54  /* Flags computed by finalize method.  */
55
56  /* Total number of accesses in loads tree.  */
57  unsigned int load_accesses;
58  /* global_memory_read is not set for functions calling functions
59     with !binds_to_current_def which, after interposition, may read global
60     memory but do nothing useful with it (except for crashing if some
61     stores are optimized out.  */
62  unsigned global_memory_read : 1;
63  unsigned global_memory_written : 1;
64  unsigned try_dse : 1;
65
66
67  modref_summary ();
68  ~modref_summary ();
69  void dump (FILE *);
70  bool useful_p (int ecf_flags, bool check_flags = true);
71  void finalize (tree);
72};
73
74modref_summary *get_modref_function_summary (cgraph_node *func);
75modref_summary *get_modref_function_summary (gcall *call, bool *interposed);
76void ipa_modref_cc_finalize ();
77void ipa_merge_modref_summary_after_inlining (cgraph_edge *e);
78
79/* All flags that are implied by the ECF_CONST functions.  */
80static const int implicit_const_eaf_flags
81   = EAF_NO_DIRECT_CLOBBER | EAF_NO_INDIRECT_CLOBBER
82    | EAF_NO_DIRECT_ESCAPE | EAF_NO_INDIRECT_ESCAPE
83    | EAF_NO_DIRECT_READ | EAF_NO_INDIRECT_READ
84    | EAF_NOT_RETURNED_INDIRECTLY;
85
86/* All flags that are implied by the ECF_PURE function.  */
87static const int implicit_pure_eaf_flags
88   = EAF_NO_DIRECT_CLOBBER | EAF_NO_INDIRECT_CLOBBER
89    | EAF_NO_DIRECT_ESCAPE | EAF_NO_INDIRECT_ESCAPE;
90
91/* All flags implied when we know we can ignore stores (i.e. when handling
92   call to noreturn).  */
93static const int ignore_stores_eaf_flags
94   = EAF_NO_DIRECT_CLOBBER | EAF_NO_INDIRECT_CLOBBER
95    | EAF_NO_DIRECT_ESCAPE | EAF_NO_INDIRECT_ESCAPE;
96
97/* Return slot is write-only.  */
98static const int implicit_retslot_eaf_flags
99   = EAF_NO_DIRECT_READ | EAF_NO_INDIRECT_READ
100     | EAF_NO_INDIRECT_ESCAPE | EAF_NO_INDIRECT_CLOBBER
101     | EAF_NOT_RETURNED_INDIRECTLY;
102
103/* If function does not bind to current def (i.e. it is inline in comdat
104   section), the modref analysis may not match the behavior of function
105   which will be later symbol interposed to.  All side effects must match
106   however it is possible that the other function body contains more loads
107   which may trap.
108   MODREF_FLAGS are flags determined by analysis of function body while
109   FLAGS are flags known otherwise (i.e. by fnspec, pure/const attributes
110   etc.)  */
111static inline int
112interposable_eaf_flags (int modref_flags, int flags)
113{
114  /* If parameter was previously unused, we know it is only read
115     and its value is not used.  */
116  if ((modref_flags & EAF_UNUSED) && !(flags & EAF_UNUSED))
117    {
118      modref_flags &= ~EAF_UNUSED;
119      modref_flags |= EAF_NO_DIRECT_ESCAPE | EAF_NO_INDIRECT_ESCAPE
120		      | EAF_NOT_RETURNED_DIRECTLY | EAF_NOT_RETURNED_INDIRECTLY
121		      | EAF_NO_DIRECT_CLOBBER | EAF_NO_INDIRECT_CLOBBER;
122    }
123  /* We can not determine that value is not read at all.  */
124  if ((modref_flags & EAF_NO_DIRECT_READ) && !(flags & EAF_NO_DIRECT_READ))
125    modref_flags &= ~EAF_NO_DIRECT_READ;
126  if ((modref_flags & EAF_NO_INDIRECT_READ) && !(flags & EAF_NO_INDIRECT_READ))
127    modref_flags &= ~EAF_NO_INDIRECT_READ;
128  return modref_flags;
129}
130
131#endif
132