Branch data Line data Source code
1 : : /* Search for references that a functions loads or stores.
2 : : Copyright (C) 2019-2025 Free Software Foundation, Inc.
3 : :
4 : : This file is part of GCC.
5 : :
6 : : GCC is free software; you can redistribute it and/or modify it under
7 : : the terms of the GNU General Public License as published by the Free
8 : : Software Foundation; either version 3, or (at your option) any later
9 : : version.
10 : :
11 : : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 : : WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 : : FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 : : for more details.
15 : :
16 : : You should have received a copy of the GNU General Public License
17 : : along 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 : :
23 : : typedef modref_tree <alias_set_type> modref_records;
24 : : typedef unsigned short eaf_flags_t;
25 : :
26 : : /* Single function summary. */
27 : :
28 : : struct 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 *) const;
70 : : bool useful_p (int ecf_flags, bool check_flags = true);
71 : : void finalize (tree);
72 : : };
73 : :
74 : : modref_summary *get_modref_function_summary (cgraph_node *func);
75 : : modref_summary *get_modref_function_summary (gcall *call, bool *interposed);
76 : : void ipa_modref_cc_finalize ();
77 : : void ipa_merge_modref_summary_after_inlining (cgraph_edge *e);
78 : : bool ipa_modref_callee_reads_no_memory_p (gcall *call);
79 : :
80 : : /* All flags that are implied by the ECF_CONST functions. */
81 : : static const int implicit_const_eaf_flags
82 : : = EAF_NO_DIRECT_CLOBBER | EAF_NO_INDIRECT_CLOBBER
83 : : | EAF_NO_DIRECT_ESCAPE | EAF_NO_INDIRECT_ESCAPE
84 : : | EAF_NO_DIRECT_READ | EAF_NO_INDIRECT_READ
85 : : | EAF_NOT_RETURNED_INDIRECTLY;
86 : :
87 : : /* All flags that are implied by the ECF_PURE function. */
88 : : static const int implicit_pure_eaf_flags
89 : : = EAF_NO_DIRECT_CLOBBER | EAF_NO_INDIRECT_CLOBBER
90 : : | EAF_NO_DIRECT_ESCAPE | EAF_NO_INDIRECT_ESCAPE;
91 : :
92 : : /* All flags implied when we know we can ignore stores (i.e. when handling
93 : : call to noreturn). */
94 : : static const int ignore_stores_eaf_flags
95 : : = EAF_NO_DIRECT_CLOBBER | EAF_NO_INDIRECT_CLOBBER
96 : : | EAF_NO_DIRECT_ESCAPE | EAF_NO_INDIRECT_ESCAPE;
97 : :
98 : : /* Return slot is write-only. */
99 : : static const int implicit_retslot_eaf_flags
100 : : = EAF_NO_DIRECT_READ | EAF_NO_INDIRECT_READ
101 : : | EAF_NO_INDIRECT_ESCAPE | EAF_NO_INDIRECT_CLOBBER
102 : : | EAF_NOT_RETURNED_INDIRECTLY;
103 : :
104 : : /* If function does not bind to current def (i.e. it is inline in comdat
105 : : section), the modref analysis may not match the behavior of function
106 : : which will be later symbol interposed to. All side effects must match
107 : : however it is possible that the other function body contains more loads
108 : : which may trap.
109 : : MODREF_FLAGS are flags determined by analysis of function body while
110 : : FLAGS are flags known otherwise (i.e. by fnspec, pure/const attributes
111 : : etc.) */
112 : : inline int
113 : 8038336 : interposable_eaf_flags (int modref_flags, int flags)
114 : : {
115 : : /* If parameter was previously unused, we know it is only read
116 : : and its value is not used. */
117 : 8038336 : if ((modref_flags & EAF_UNUSED) && !(flags & EAF_UNUSED))
118 : : {
119 : 384427 : modref_flags &= ~EAF_UNUSED;
120 : 384427 : modref_flags |= EAF_NO_DIRECT_ESCAPE | EAF_NO_INDIRECT_ESCAPE
121 : : | EAF_NOT_RETURNED_DIRECTLY | EAF_NOT_RETURNED_INDIRECTLY
122 : : | EAF_NO_DIRECT_CLOBBER | EAF_NO_INDIRECT_CLOBBER;
123 : : }
124 : : /* We can not determine that value is not read at all. */
125 : 8038336 : if ((modref_flags & EAF_NO_DIRECT_READ) && !(flags & EAF_NO_DIRECT_READ))
126 : 611077 : modref_flags &= ~EAF_NO_DIRECT_READ;
127 : 8038336 : if ((modref_flags & EAF_NO_INDIRECT_READ) && !(flags & EAF_NO_INDIRECT_READ))
128 : 897365 : modref_flags &= ~EAF_NO_INDIRECT_READ;
129 : 8038336 : return modref_flags;
130 : : }
131 : :
132 : : #endif
|