Line data Source code
1 : /* Search for references that a functions loads or stores.
2 : Copyright (C) 2019-2026 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 9820761 : 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 9820761 : if ((modref_flags & EAF_UNUSED) && !(flags & EAF_UNUSED))
118 : {
119 531606 : modref_flags &= ~EAF_UNUSED;
120 531606 : 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 9820761 : if ((modref_flags & EAF_NO_DIRECT_READ) && !(flags & EAF_NO_DIRECT_READ))
126 684176 : modref_flags &= ~EAF_NO_DIRECT_READ;
127 9820761 : if ((modref_flags & EAF_NO_INDIRECT_READ) && !(flags & EAF_NO_INDIRECT_READ))
128 992694 : modref_flags &= ~EAF_NO_INDIRECT_READ;
129 9820761 : return modref_flags;
130 : }
131 :
132 : #endif
|