Mercurial > hg > CbC > CbC_gcc
annotate gcc/ipa-pure-const.c @ 158:494b0b89df80 default tip
...
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Mon, 25 May 2020 18:13:55 +0900 |
parents | 1830386684a0 |
children |
rev | line source |
---|---|
0 | 1 /* Callgraph based analysis of static variables. |
145 | 2 Copyright (C) 2004-2020 Free Software Foundation, Inc. |
0 | 3 Contributed by Kenneth Zadeck <zadeck@naturalbridge.com> |
4 | |
5 This file is part of GCC. | |
6 | |
7 GCC is free software; you can redistribute it and/or modify it under | |
8 the terms of the GNU General Public License as published by the Free | |
9 Software Foundation; either version 3, or (at your option) any later | |
10 version. | |
11 | |
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
15 for more details. | |
16 | |
17 You should have received a copy of the GNU General Public License | |
18 along with GCC; see the file COPYING3. If not see | |
19 <http://www.gnu.org/licenses/>. */ | |
20 | |
21 /* This file marks functions as being either const (TREE_READONLY) or | |
22 pure (DECL_PURE_P). It can also set a variant of these that | |
23 are allowed to loop indefinitely (DECL_LOOPING_CONST_PURE_P). | |
24 | |
25 This must be run after inlining decisions have been made since | |
26 otherwise, the local sets will not contain information that is | |
27 consistent with post inlined state. The global sets are not prone | |
28 to this problem since they are by definition transitive. */ | |
29 | |
30 /* The code in this module is called by the ipa pass manager. It | |
31 should be one of the later passes since it's information is used by | |
32 the rest of the compilation. */ | |
33 | |
34 #include "config.h" | |
35 #include "system.h" | |
36 #include "coretypes.h" | |
111 | 37 #include "backend.h" |
38 #include "target.h" | |
0 | 39 #include "tree.h" |
40 #include "gimple.h" | |
111 | 41 #include "tree-pass.h" |
42 #include "tree-streamer.h" | |
0 | 43 #include "cgraph.h" |
44 #include "diagnostic.h" | |
111 | 45 #include "calls.h" |
46 #include "cfganal.h" | |
47 #include "tree-eh.h" | |
48 #include "gimple-iterator.h" | |
49 #include "gimple-walk.h" | |
50 #include "tree-cfg.h" | |
51 #include "tree-ssa-loop-niter.h" | |
0 | 52 #include "langhooks.h" |
111 | 53 #include "ipa-utils.h" |
54 #include "gimple-pretty-print.h" | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
55 #include "cfgloop.h" |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
56 #include "tree-scalar-evolution.h" |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
57 #include "intl.h" |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
58 #include "opts.h" |
131 | 59 #include "ssa.h" |
60 #include "alloc-pool.h" | |
61 #include "symbol-summary.h" | |
62 #include "ipa-prop.h" | |
63 #include "ipa-fnsummary.h" | |
0 | 64 |
65 /* Lattice values for const and pure functions. Everything starts out | |
66 being const, then may drop to pure and then neither depending on | |
67 what is found. */ | |
68 enum pure_const_state_e | |
69 { | |
70 IPA_CONST, | |
71 IPA_PURE, | |
72 IPA_NEITHER | |
73 }; | |
74 | |
131 | 75 static const char *pure_const_names[3] = {"const", "pure", "neither"}; |
76 | |
77 enum malloc_state_e | |
78 { | |
79 STATE_MALLOC_TOP, | |
80 STATE_MALLOC, | |
81 STATE_MALLOC_BOTTOM | |
82 }; | |
83 | |
84 static const char *malloc_state_names[] = {"malloc_top", "malloc", "malloc_bottom"}; | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
85 |
0 | 86 /* Holder for the const_state. There is one of these per function |
87 decl. */ | |
131 | 88 class funct_state_d |
0 | 89 { |
131 | 90 public: |
91 funct_state_d (): pure_const_state (IPA_NEITHER), | |
92 state_previously_known (IPA_NEITHER), looping_previously_known (true), | |
93 looping (true), can_throw (true), can_free (true), | |
94 malloc_state (STATE_MALLOC_BOTTOM) {} | |
95 | |
96 funct_state_d (const funct_state_d &s): pure_const_state (s.pure_const_state), | |
97 state_previously_known (s.state_previously_known), | |
98 looping_previously_known (s.looping_previously_known), | |
99 looping (s.looping), can_throw (s.can_throw), can_free (s.can_free), | |
100 malloc_state (s.malloc_state) {} | |
101 | |
0 | 102 /* See above. */ |
103 enum pure_const_state_e pure_const_state; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
104 /* What user set here; we can be always sure about this. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
105 enum pure_const_state_e state_previously_known; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
106 bool looping_previously_known; |
0 | 107 |
108 /* True if the function could possibly infinite loop. There are a | |
109 lot of ways that this could be determined. We are pretty | |
110 conservative here. While it is possible to cse pure and const | |
111 calls, it is not legal to have dce get rid of the call if there | |
112 is a possibility that the call could infinite loop since this is | |
113 a behavioral change. */ | |
114 bool looping; | |
115 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
116 bool can_throw; |
111 | 117 |
118 /* If function can call free, munmap or otherwise make previously | |
119 non-trapping memory accesses trapping. */ | |
120 bool can_free; | |
131 | 121 |
122 enum malloc_state_e malloc_state; | |
0 | 123 }; |
124 | |
145 | 125 typedef class funct_state_d * funct_state; |
0 | 126 |
127 /* The storage of the funct_state is abstracted because there is the | |
128 possibility that it may be desirable to move this to the cgraph | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
129 local info. */ |
0 | 130 |
145 | 131 class funct_state_summary_t: |
132 public fast_function_summary <funct_state_d *, va_heap> | |
131 | 133 { |
134 public: | |
135 funct_state_summary_t (symbol_table *symtab): | |
145 | 136 fast_function_summary <funct_state_d *, va_heap> (symtab) {} |
0 | 137 |
131 | 138 virtual void insert (cgraph_node *, funct_state_d *state); |
139 virtual void duplicate (cgraph_node *src_node, cgraph_node *dst_node, | |
140 funct_state_d *src_data, | |
141 funct_state_d *dst_data); | |
142 }; | |
143 | |
144 static funct_state_summary_t *funct_state_summaries = NULL; | |
111 | 145 |
146 static bool gate_pure_const (void); | |
147 | |
148 namespace { | |
149 | |
150 const pass_data pass_data_ipa_pure_const = | |
151 { | |
152 IPA_PASS, /* type */ | |
153 "pure-const", /* name */ | |
154 OPTGROUP_NONE, /* optinfo_flags */ | |
155 TV_IPA_PURE_CONST, /* tv_id */ | |
156 0, /* properties_required */ | |
157 0, /* properties_provided */ | |
158 0, /* properties_destroyed */ | |
159 0, /* todo_flags_start */ | |
160 0, /* todo_flags_finish */ | |
161 }; | |
0 | 162 |
111 | 163 class pass_ipa_pure_const : public ipa_opt_pass_d |
164 { | |
165 public: | |
166 pass_ipa_pure_const(gcc::context *ctxt); | |
167 | |
168 /* opt_pass methods: */ | |
169 bool gate (function *) { return gate_pure_const (); } | |
170 unsigned int execute (function *fun); | |
171 | |
172 void register_hooks (void); | |
173 | |
174 private: | |
175 bool init_p; | |
176 }; // class pass_ipa_pure_const | |
177 | |
178 } // anon namespace | |
0 | 179 |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
180 /* Try to guess if function body will always be visible to compiler |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
181 when compiling the call and whether compiler will be able |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
182 to propagate the information by itself. */ |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
183 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
184 static bool |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
185 function_always_visible_to_compiler_p (tree decl) |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
186 { |
111 | 187 return (!TREE_PUBLIC (decl) || DECL_DECLARED_INLINE_P (decl) |
188 || DECL_COMDAT (decl)); | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
189 } |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
190 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
191 /* Emit suggestion about attribute ATTRIB_NAME for DECL. KNOWN_FINITE |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
192 is true if the function is known to be finite. The diagnostic is |
111 | 193 controlled by OPTION. WARNED_ABOUT is a hash_set<tree> unique for |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
194 OPTION, this function may initialize it and it is always returned |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
195 by the function. */ |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
196 |
111 | 197 static hash_set<tree> * |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
198 suggest_attribute (int option, tree decl, bool known_finite, |
111 | 199 hash_set<tree> *warned_about, |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
200 const char * attrib_name) |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
201 { |
145 | 202 if (!option_enabled (option, lang_hooks.option_lang_mask (), &global_options)) |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
203 return warned_about; |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
204 if (TREE_THIS_VOLATILE (decl) |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
205 || (known_finite && function_always_visible_to_compiler_p (decl))) |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
206 return warned_about; |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
207 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
208 if (!warned_about) |
111 | 209 warned_about = new hash_set<tree>; |
210 if (warned_about->contains (decl)) | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
211 return warned_about; |
111 | 212 warned_about->add (decl); |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
213 warning_at (DECL_SOURCE_LOCATION (decl), |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
214 option, |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
215 known_finite |
111 | 216 ? G_("function might be candidate for attribute %qs") |
217 : G_("function might be candidate for attribute %qs" | |
218 " if it is known to return normally"), attrib_name); | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
219 return warned_about; |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
220 } |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
221 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
222 /* Emit suggestion about __attribute_((pure)) for DECL. KNOWN_FINITE |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
223 is true if the function is known to be finite. */ |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
224 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
225 static void |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
226 warn_function_pure (tree decl, bool known_finite) |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
227 { |
131 | 228 /* Declaring a void function pure makes no sense and is diagnosed |
229 by -Wattributes because calling it would have no effect. */ | |
230 if (VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl)))) | |
231 return; | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
232 |
131 | 233 static hash_set<tree> *warned_about; |
234 warned_about | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
235 = suggest_attribute (OPT_Wsuggest_attribute_pure, decl, |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
236 known_finite, warned_about, "pure"); |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
237 } |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
238 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
239 /* Emit suggestion about __attribute_((const)) for DECL. KNOWN_FINITE |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
240 is true if the function is known to be finite. */ |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
241 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
242 static void |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
243 warn_function_const (tree decl, bool known_finite) |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
244 { |
131 | 245 /* Declaring a void function const makes no sense is diagnosed |
246 by -Wattributes because calling it would have no effect. */ | |
247 if (VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl)))) | |
248 return; | |
249 | |
111 | 250 static hash_set<tree> *warned_about; |
131 | 251 warned_about |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
252 = suggest_attribute (OPT_Wsuggest_attribute_const, decl, |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
253 known_finite, warned_about, "const"); |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
254 } |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
255 |
131 | 256 /* Emit suggestion about __attribute__((malloc)) for DECL. */ |
257 | |
258 static void | |
259 warn_function_malloc (tree decl) | |
260 { | |
261 static hash_set<tree> *warned_about; | |
262 warned_about | |
263 = suggest_attribute (OPT_Wsuggest_attribute_malloc, decl, | |
264 true, warned_about, "malloc"); | |
265 } | |
266 | |
267 /* Emit suggestion about __attribute__((noreturn)) for DECL. */ | |
268 | |
111 | 269 static void |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
270 warn_function_noreturn (tree decl) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
271 { |
111 | 272 tree original_decl = decl; |
273 | |
274 static hash_set<tree> *warned_about; | |
275 if (!lang_hooks.missing_noreturn_ok_p (decl) | |
276 && targetm.warn_func_return (decl)) | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
277 warned_about |
111 | 278 = suggest_attribute (OPT_Wsuggest_attribute_noreturn, original_decl, |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
279 true, warned_about, "noreturn"); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
280 } |
111 | 281 |
282 void | |
283 warn_function_cold (tree decl) | |
284 { | |
285 tree original_decl = decl; | |
0 | 286 |
111 | 287 static hash_set<tree> *warned_about; |
288 warned_about | |
289 = suggest_attribute (OPT_Wsuggest_attribute_cold, original_decl, | |
290 true, warned_about, "cold"); | |
0 | 291 } |
292 | |
293 /* Check to see if the use (or definition when CHECKING_WRITE is true) | |
294 variable T is legal in a function that is either pure or const. */ | |
295 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
296 static inline void |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
297 check_decl (funct_state local, |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
298 tree t, bool checking_write, bool ipa) |
0 | 299 { |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
300 /* Do not want to do anything with volatile except mark any |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
301 function that uses one to be not const or pure. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
302 if (TREE_THIS_VOLATILE (t)) |
0 | 303 { |
304 local->pure_const_state = IPA_NEITHER; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
305 if (dump_file) |
131 | 306 fprintf (dump_file, " Volatile operand is not const/pure\n"); |
0 | 307 return; |
308 } | |
309 | |
310 /* Do not care about a local automatic that is not static. */ | |
311 if (!TREE_STATIC (t) && !DECL_EXTERNAL (t)) | |
312 return; | |
313 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
314 /* If the variable has the "used" attribute, treat it as if it had a |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
315 been touched by the devil. */ |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
316 if (DECL_PRESERVE_P (t)) |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
317 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
318 local->pure_const_state = IPA_NEITHER; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
319 if (dump_file) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
320 fprintf (dump_file, " Used static/global variable is not const/pure\n"); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
321 return; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
322 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
323 |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
324 /* In IPA mode we are not interested in checking actual loads and stores; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
325 they will be processed at propagation time using ipa_ref. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
326 if (ipa) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
327 return; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
328 |
0 | 329 /* Since we have dealt with the locals and params cases above, if we |
330 are CHECKING_WRITE, this cannot be a pure or constant | |
331 function. */ | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
332 if (checking_write) |
0 | 333 { |
334 local->pure_const_state = IPA_NEITHER; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
335 if (dump_file) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
336 fprintf (dump_file, " static/global memory write is not const/pure\n"); |
0 | 337 return; |
338 } | |
339 | |
340 if (DECL_EXTERNAL (t) || TREE_PUBLIC (t)) | |
341 { | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
342 /* Readonly reads are safe. */ |
145 | 343 if (TREE_READONLY (t)) |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
344 return; /* Read of a constant, do not change the function state. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
345 else |
0 | 346 { |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
347 if (dump_file) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
348 fprintf (dump_file, " global memory read is not const\n"); |
0 | 349 /* Just a regular read. */ |
350 if (local->pure_const_state == IPA_CONST) | |
351 local->pure_const_state = IPA_PURE; | |
352 } | |
353 } | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
354 else |
0 | 355 { |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
356 /* Compilation level statics can be read if they are readonly |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
357 variables. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
358 if (TREE_READONLY (t)) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
359 return; |
0 | 360 |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
361 if (dump_file) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
362 fprintf (dump_file, " static memory read is not const\n"); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
363 /* Just a regular read. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
364 if (local->pure_const_state == IPA_CONST) |
0 | 365 local->pure_const_state = IPA_PURE; |
366 } | |
367 } | |
368 | |
369 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
370 /* Check to see if the use (or definition when CHECKING_WRITE is true) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
371 variable T is legal in a function that is either pure or const. */ |
0 | 372 |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
373 static inline void |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
374 check_op (funct_state local, tree t, bool checking_write) |
0 | 375 { |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
376 t = get_base_address (t); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
377 if (t && TREE_THIS_VOLATILE (t)) |
0 | 378 { |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
379 local->pure_const_state = IPA_NEITHER; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
380 if (dump_file) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
381 fprintf (dump_file, " Volatile indirect ref is not const/pure\n"); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
382 return; |
0 | 383 } |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
384 else if (t |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
385 && (INDIRECT_REF_P (t) || TREE_CODE (t) == MEM_REF) |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
386 && TREE_CODE (TREE_OPERAND (t, 0)) == SSA_NAME |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
387 && !ptr_deref_may_alias_global_p (TREE_OPERAND (t, 0))) |
0 | 388 { |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
389 if (dump_file) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
390 fprintf (dump_file, " Indirect ref to local memory is OK\n"); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
391 return; |
0 | 392 } |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
393 else if (checking_write) |
0 | 394 { |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
395 local->pure_const_state = IPA_NEITHER; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
396 if (dump_file) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
397 fprintf (dump_file, " Indirect ref write is not const/pure\n"); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
398 return; |
0 | 399 } |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
400 else |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
401 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
402 if (dump_file) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
403 fprintf (dump_file, " Indirect ref read is not const\n"); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
404 if (local->pure_const_state == IPA_CONST) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
405 local->pure_const_state = IPA_PURE; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
406 } |
0 | 407 } |
408 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
409 /* compute state based on ECF FLAGS and store to STATE and LOOPING. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
410 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
411 static void |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
412 state_from_flags (enum pure_const_state_e *state, bool *looping, |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
413 int flags, bool cannot_lead_to_return) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
414 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
415 *looping = false; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
416 if (flags & ECF_LOOPING_CONST_OR_PURE) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
417 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
418 *looping = true; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
419 if (dump_file && (dump_flags & TDF_DETAILS)) |
131 | 420 fprintf (dump_file, " looping\n"); |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
421 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
422 if (flags & ECF_CONST) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
423 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
424 *state = IPA_CONST; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
425 if (dump_file && (dump_flags & TDF_DETAILS)) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
426 fprintf (dump_file, " const\n"); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
427 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
428 else if (flags & ECF_PURE) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
429 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
430 *state = IPA_PURE; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
431 if (dump_file && (dump_flags & TDF_DETAILS)) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
432 fprintf (dump_file, " pure\n"); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
433 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
434 else if (cannot_lead_to_return) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
435 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
436 *state = IPA_PURE; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
437 *looping = true; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
438 if (dump_file && (dump_flags & TDF_DETAILS)) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
439 fprintf (dump_file, " ignoring side effects->pure looping\n"); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
440 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
441 else |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
442 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
443 if (dump_file && (dump_flags & TDF_DETAILS)) |
111 | 444 fprintf (dump_file, " neither\n"); |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
445 *state = IPA_NEITHER; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
446 *looping = true; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
447 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
448 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
449 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
450 /* Merge STATE and STATE2 and LOOPING and LOOPING2 and store |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
451 into STATE and LOOPING better of the two variants. |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
452 Be sure to merge looping correctly. IPA_NEITHER functions |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
453 have looping 0 even if they don't have to return. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
454 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
455 static inline void |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
456 better_state (enum pure_const_state_e *state, bool *looping, |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
457 enum pure_const_state_e state2, bool looping2) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
458 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
459 if (state2 < *state) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
460 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
461 if (*state == IPA_NEITHER) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
462 *looping = looping2; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
463 else |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
464 *looping = MIN (*looping, looping2); |
111 | 465 *state = state2; |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
466 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
467 else if (state2 != IPA_NEITHER) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
468 *looping = MIN (*looping, looping2); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
469 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
470 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
471 /* Merge STATE and STATE2 and LOOPING and LOOPING2 and store |
111 | 472 into STATE and LOOPING worse of the two variants. |
473 N is the actual node called. */ | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
474 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
475 static inline void |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
476 worse_state (enum pure_const_state_e *state, bool *looping, |
111 | 477 enum pure_const_state_e state2, bool looping2, |
478 struct symtab_node *from, | |
479 struct symtab_node *to) | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
480 { |
111 | 481 /* Consider function: |
482 | |
483 bool a(int *p) | |
484 { | |
485 return *p==*p; | |
486 } | |
487 | |
488 During early optimization we will turn this into: | |
489 | |
490 bool a(int *p) | |
491 { | |
492 return true; | |
493 } | |
494 | |
495 Now if this function will be detected as CONST however when interposed it | |
496 may end up being just pure. We always must assume the worst scenario here. | |
497 */ | |
498 if (*state == IPA_CONST && state2 == IPA_CONST | |
499 && to && !TREE_READONLY (to->decl) && !to->binds_to_current_def_p (from)) | |
500 { | |
501 if (dump_file && (dump_flags & TDF_DETAILS)) | |
502 fprintf (dump_file, "Dropping state to PURE because call to %s may not " | |
145 | 503 "bind to current def.\n", to->dump_name ()); |
111 | 504 state2 = IPA_PURE; |
505 } | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
506 *state = MAX (*state, state2); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
507 *looping = MAX (*looping, looping2); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
508 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
509 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
510 /* Recognize special cases of builtins that are by themselves not pure or const |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
511 but function using them is. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
512 static bool |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
513 special_builtin_state (enum pure_const_state_e *state, bool *looping, |
145 | 514 tree callee) |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
515 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
516 if (DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
517 switch (DECL_FUNCTION_CODE (callee)) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
518 { |
145 | 519 case BUILT_IN_RETURN: |
520 case BUILT_IN_UNREACHABLE: | |
521 CASE_BUILT_IN_ALLOCA: | |
522 case BUILT_IN_STACK_SAVE: | |
523 case BUILT_IN_STACK_RESTORE: | |
524 case BUILT_IN_EH_POINTER: | |
525 case BUILT_IN_EH_FILTER: | |
526 case BUILT_IN_UNWIND_RESUME: | |
527 case BUILT_IN_CXA_END_CLEANUP: | |
528 case BUILT_IN_EH_COPY_VALUES: | |
529 case BUILT_IN_FRAME_ADDRESS: | |
530 case BUILT_IN_APPLY_ARGS: | |
531 case BUILT_IN_ASAN_BEFORE_DYNAMIC_INIT: | |
532 case BUILT_IN_ASAN_AFTER_DYNAMIC_INIT: | |
533 *looping = false; | |
534 *state = IPA_CONST; | |
535 return true; | |
536 case BUILT_IN_PREFETCH: | |
537 *looping = true; | |
538 *state = IPA_CONST; | |
539 return true; | |
540 default: | |
541 break; | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
542 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
543 return false; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
544 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
545 |
0 | 546 /* Check the parameters of a function call to CALL_EXPR to see if |
547 there are any references in the parameters that are not allowed for | |
548 pure or const functions. Also check to see if this is either an | |
549 indirect call, a call outside the compilation unit, or has special | |
550 attributes that may also effect the purity. The CALL_EXPR node for | |
551 the entire call expression. */ | |
552 | |
553 static void | |
111 | 554 check_call (funct_state local, gcall *call, bool ipa) |
0 | 555 { |
556 int flags = gimple_call_flags (call); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
557 tree callee_t = gimple_call_fndecl (call); |
131 | 558 bool possibly_throws = stmt_could_throw_p (cfun, call); |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
559 bool possibly_throws_externally = (possibly_throws |
131 | 560 && stmt_can_throw_external (cfun, call)); |
0 | 561 |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
562 if (possibly_throws) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
563 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
564 unsigned int i; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
565 for (i = 0; i < gimple_num_ops (call); i++) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
566 if (gimple_op (call, i) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
567 && tree_could_throw_p (gimple_op (call, i))) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
568 { |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
569 if (possibly_throws && cfun->can_throw_non_call_exceptions) |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
570 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
571 if (dump_file) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
572 fprintf (dump_file, " operand can throw; looping\n"); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
573 local->looping = true; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
574 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
575 if (possibly_throws_externally) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
576 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
577 if (dump_file) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
578 fprintf (dump_file, " operand can throw externally\n"); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
579 local->can_throw = true; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
580 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
581 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
582 } |
0 | 583 |
584 /* The const and pure flags are set by a variety of places in the | |
585 compiler (including here). If someone has already set the flags | |
586 for the callee, (such as for some of the builtins) we will use | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
587 them, otherwise we will compute our own information. |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
588 |
0 | 589 Const and pure functions have less clobber effects than other |
590 functions so we process these first. Otherwise if it is a call | |
591 outside the compilation unit or an indirect call we punt. This | |
592 leaves local calls which will be processed by following the call | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
593 graph. */ |
0 | 594 if (callee_t) |
595 { | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
596 enum pure_const_state_e call_state; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
597 bool call_looping; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
598 |
111 | 599 if (gimple_call_builtin_p (call, BUILT_IN_NORMAL) |
600 && !nonfreeing_call_p (call)) | |
601 local->can_free = true; | |
602 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
603 if (special_builtin_state (&call_state, &call_looping, callee_t)) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
604 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
605 worse_state (&local->pure_const_state, &local->looping, |
111 | 606 call_state, call_looping, |
607 NULL, NULL); | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
608 return; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
609 } |
0 | 610 /* When bad things happen to bad functions, they cannot be const |
611 or pure. */ | |
612 if (setjmp_call_p (callee_t)) | |
613 { | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
614 if (dump_file) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
615 fprintf (dump_file, " setjmp is not const/pure\n"); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
616 local->looping = true; |
0 | 617 local->pure_const_state = IPA_NEITHER; |
618 } | |
619 | |
620 if (DECL_BUILT_IN_CLASS (callee_t) == BUILT_IN_NORMAL) | |
621 switch (DECL_FUNCTION_CODE (callee_t)) | |
622 { | |
623 case BUILT_IN_LONGJMP: | |
624 case BUILT_IN_NONLOCAL_GOTO: | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
625 if (dump_file) |
145 | 626 fprintf (dump_file, |
627 " longjmp and nonlocal goto is not const/pure\n"); | |
0 | 628 local->pure_const_state = IPA_NEITHER; |
145 | 629 local->looping = true; |
0 | 630 break; |
631 default: | |
632 break; | |
633 } | |
634 } | |
111 | 635 else if (gimple_call_internal_p (call) && !nonfreeing_call_p (call)) |
636 local->can_free = true; | |
0 | 637 |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
638 /* When not in IPA mode, we can still handle self recursion. */ |
111 | 639 if (!ipa && callee_t |
640 && recursive_call_p (current_function_decl, callee_t)) | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
641 { |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
642 if (dump_file) |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
643 fprintf (dump_file, " Recursive call can loop.\n"); |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
644 local->looping = true; |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
645 } |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
646 /* Either callee is unknown or we are doing local analysis. |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
647 Look to see if there are any bits available for the callee (such as by |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
648 declaration or because it is builtin) and process solely on the basis of |
111 | 649 those bits. Handle internal calls always, those calls don't have |
650 corresponding cgraph edges and thus aren't processed during | |
651 the propagation. */ | |
652 else if (!ipa || gimple_call_internal_p (call)) | |
0 | 653 { |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
654 enum pure_const_state_e call_state; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
655 bool call_looping; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
656 if (possibly_throws && cfun->can_throw_non_call_exceptions) |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
657 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
658 if (dump_file) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
659 fprintf (dump_file, " can throw; looping\n"); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
660 local->looping = true; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
661 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
662 if (possibly_throws_externally) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
663 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
664 if (dump_file) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
665 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
666 fprintf (dump_file, " can throw externally to lp %i\n", |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
667 lookup_stmt_eh_lp (call)); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
668 if (callee_t) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
669 fprintf (dump_file, " callee:%s\n", |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
670 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (callee_t))); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
671 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
672 local->can_throw = true; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
673 } |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
674 if (dump_file && (dump_flags & TDF_DETAILS)) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
675 fprintf (dump_file, " checking flags for call:"); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
676 state_from_flags (&call_state, &call_looping, flags, |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
677 ((flags & (ECF_NORETURN | ECF_NOTHROW)) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
678 == (ECF_NORETURN | ECF_NOTHROW)) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
679 || (!flag_exceptions && (flags & ECF_NORETURN))); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
680 worse_state (&local->pure_const_state, &local->looping, |
111 | 681 call_state, call_looping, NULL, NULL); |
0 | 682 } |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
683 /* Direct functions calls are handled by IPA propagation. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
684 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
685 |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
686 /* Wrapper around check_decl for loads in local more. */ |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
687 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
688 static bool |
111 | 689 check_load (gimple *, tree op, tree, void *data) |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
690 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
691 if (DECL_P (op)) |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
692 check_decl ((funct_state)data, op, false, false); |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
693 else |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
694 check_op ((funct_state)data, op, false); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
695 return false; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
696 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
697 |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
698 /* Wrapper around check_decl for stores in local more. */ |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
699 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
700 static bool |
111 | 701 check_store (gimple *, tree op, tree, void *data) |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
702 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
703 if (DECL_P (op)) |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
704 check_decl ((funct_state)data, op, true, false); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
705 else |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
706 check_op ((funct_state)data, op, true); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
707 return false; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
708 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
709 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
710 /* Wrapper around check_decl for loads in ipa mode. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
711 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
712 static bool |
111 | 713 check_ipa_load (gimple *, tree op, tree, void *data) |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
714 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
715 if (DECL_P (op)) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
716 check_decl ((funct_state)data, op, false, true); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
717 else |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
718 check_op ((funct_state)data, op, false); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
719 return false; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
720 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
721 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
722 /* Wrapper around check_decl for stores in ipa mode. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
723 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
724 static bool |
111 | 725 check_ipa_store (gimple *, tree op, tree, void *data) |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
726 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
727 if (DECL_P (op)) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
728 check_decl ((funct_state)data, op, true, true); |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
729 else |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
730 check_op ((funct_state)data, op, true); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
731 return false; |
0 | 732 } |
733 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
734 /* Look into pointer pointed to by GSIP and figure out what interesting side |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
735 effects it has. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
736 static void |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
737 check_stmt (gimple_stmt_iterator *gsip, funct_state local, bool ipa) |
0 | 738 { |
111 | 739 gimple *stmt = gsi_stmt (*gsip); |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
740 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
741 if (is_gimple_debug (stmt)) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
742 return; |
0 | 743 |
111 | 744 /* Do consider clobber as side effects before IPA, so we rather inline |
745 C++ destructors and keep clobber semantics than eliminate them. | |
746 | |
747 TODO: We may get smarter during early optimizations on these and let | |
748 functions containing only clobbers to be optimized more. This is a common | |
749 case of C++ destructors. */ | |
750 | |
751 if ((ipa || cfun->after_inlining) && gimple_clobber_p (stmt)) | |
752 return; | |
753 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
754 if (dump_file) |
0 | 755 { |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
756 fprintf (dump_file, " scanning: "); |
111 | 757 print_gimple_stmt (dump_file, stmt, 0); |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
758 } |
0 | 759 |
111 | 760 if (gimple_has_volatile_ops (stmt) |
761 && !gimple_clobber_p (stmt)) | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
762 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
763 local->pure_const_state = IPA_NEITHER; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
764 if (dump_file) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
765 fprintf (dump_file, " Volatile stmt is not const/pure\n"); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
766 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
767 |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
768 /* Look for loads and stores. */ |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
769 walk_stmt_load_store_ops (stmt, local, |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
770 ipa ? check_ipa_load : check_load, |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
771 ipa ? check_ipa_store : check_store); |
0 | 772 |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
773 if (gimple_code (stmt) != GIMPLE_CALL |
131 | 774 && stmt_could_throw_p (cfun, stmt)) |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
775 { |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
776 if (cfun->can_throw_non_call_exceptions) |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
777 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
778 if (dump_file) |
111 | 779 fprintf (dump_file, " can throw; looping\n"); |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
780 local->looping = true; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
781 } |
131 | 782 if (stmt_can_throw_external (cfun, stmt)) |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
783 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
784 if (dump_file) |
111 | 785 fprintf (dump_file, " can throw externally\n"); |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
786 local->can_throw = true; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
787 } |
111 | 788 else |
789 if (dump_file) | |
790 fprintf (dump_file, " can throw\n"); | |
0 | 791 } |
792 switch (gimple_code (stmt)) | |
793 { | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
794 case GIMPLE_CALL: |
111 | 795 check_call (local, as_a <gcall *> (stmt), ipa); |
0 | 796 break; |
797 case GIMPLE_LABEL: | |
111 | 798 if (DECL_NONLOCAL (gimple_label_label (as_a <glabel *> (stmt)))) |
0 | 799 /* Target of long jump. */ |
800 { | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
801 if (dump_file) |
111 | 802 fprintf (dump_file, " nonlocal label is not const/pure\n"); |
0 | 803 local->pure_const_state = IPA_NEITHER; |
804 } | |
805 break; | |
806 case GIMPLE_ASM: | |
111 | 807 if (gimple_asm_clobbers_memory_p (as_a <gasm *> (stmt))) |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
808 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
809 if (dump_file) |
111 | 810 fprintf (dump_file, " memory asm clobber is not const/pure\n"); |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
811 /* Abandon all hope, ye who enter here. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
812 local->pure_const_state = IPA_NEITHER; |
111 | 813 local->can_free = true; |
814 } | |
815 if (gimple_asm_volatile_p (as_a <gasm *> (stmt))) | |
816 { | |
817 if (dump_file) | |
818 fprintf (dump_file, " volatile is not const/pure\n"); | |
819 /* Abandon all hope, ye who enter here. */ | |
820 local->pure_const_state = IPA_NEITHER; | |
821 local->looping = true; | |
822 local->can_free = true; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
823 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
824 return; |
0 | 825 default: |
826 break; | |
827 } | |
828 } | |
829 | |
131 | 830 /* Check that RETVAL is used only in STMT and in comparisons against 0. |
831 RETVAL is return value of the function and STMT is return stmt. */ | |
832 | |
833 static bool | |
834 check_retval_uses (tree retval, gimple *stmt) | |
835 { | |
836 imm_use_iterator use_iter; | |
837 gimple *use_stmt; | |
838 | |
839 FOR_EACH_IMM_USE_STMT (use_stmt, use_iter, retval) | |
840 if (gcond *cond = dyn_cast<gcond *> (use_stmt)) | |
841 { | |
842 tree op2 = gimple_cond_rhs (cond); | |
843 if (!integer_zerop (op2)) | |
844 RETURN_FROM_IMM_USE_STMT (use_iter, false); | |
845 } | |
846 else if (gassign *ga = dyn_cast<gassign *> (use_stmt)) | |
847 { | |
848 enum tree_code code = gimple_assign_rhs_code (ga); | |
849 if (TREE_CODE_CLASS (code) != tcc_comparison) | |
850 RETURN_FROM_IMM_USE_STMT (use_iter, false); | |
851 if (!integer_zerop (gimple_assign_rhs2 (ga))) | |
852 RETURN_FROM_IMM_USE_STMT (use_iter, false); | |
853 } | |
854 else if (is_gimple_debug (use_stmt)) | |
855 ; | |
856 else if (use_stmt != stmt) | |
857 RETURN_FROM_IMM_USE_STMT (use_iter, false); | |
858 | |
859 return true; | |
860 } | |
861 | |
862 /* malloc_candidate_p() checks if FUN can possibly be annotated with malloc | |
863 attribute. Currently this function does a very conservative analysis. | |
864 FUN is considered to be a candidate if | |
865 1) It returns a value of pointer type. | |
866 2) SSA_NAME_DEF_STMT (return_value) is either a function call or | |
867 a phi, and element of phi is either NULL or | |
868 SSA_NAME_DEF_STMT(element) is function call. | |
869 3) The return-value has immediate uses only within comparisons (gcond or gassign) | |
870 and return_stmt (and likewise a phi arg has immediate use only within comparison | |
871 or the phi stmt). */ | |
872 | |
873 #define DUMP_AND_RETURN(reason) \ | |
874 { \ | |
875 if (dump_file && (dump_flags & TDF_DETAILS)) \ | |
876 fprintf (dump_file, "\n%s is not a malloc candidate, reason: %s\n", \ | |
145 | 877 (node->dump_name ()), (reason)); \ |
131 | 878 return false; \ |
879 } | |
880 | |
881 static bool | |
145 | 882 malloc_candidate_p_1 (function *fun, tree retval, gimple *ret_stmt, bool ipa, |
883 bitmap visited) | |
131 | 884 { |
885 cgraph_node *node = cgraph_node::get_create (fun->decl); | |
145 | 886 if (!bitmap_set_bit (visited, SSA_NAME_VERSION (retval))) |
887 return true; | |
131 | 888 |
889 if (!check_retval_uses (retval, ret_stmt)) | |
890 DUMP_AND_RETURN("Return value has uses outside return stmt" | |
891 " and comparisons against 0.") | |
892 | |
893 gimple *def = SSA_NAME_DEF_STMT (retval); | |
894 | |
895 if (gcall *call_stmt = dyn_cast<gcall *> (def)) | |
896 { | |
897 tree callee_decl = gimple_call_fndecl (call_stmt); | |
898 if (!callee_decl) | |
899 return false; | |
900 | |
901 if (!ipa && !DECL_IS_MALLOC (callee_decl)) | |
902 DUMP_AND_RETURN("callee_decl does not have malloc attribute for" | |
903 " non-ipa mode.") | |
904 | |
905 cgraph_edge *cs = node->get_edge (call_stmt); | |
906 if (cs) | |
907 { | |
908 ipa_call_summary *es = ipa_call_summaries->get_create (cs); | |
909 es->is_return_callee_uncaptured = true; | |
910 } | |
911 } | |
912 | |
913 else if (gphi *phi = dyn_cast<gphi *> (def)) | |
914 { | |
915 bool all_args_zero = true; | |
916 for (unsigned i = 0; i < gimple_phi_num_args (phi); ++i) | |
917 { | |
918 tree arg = gimple_phi_arg_def (phi, i); | |
919 if (integer_zerop (arg)) | |
920 continue; | |
921 | |
922 all_args_zero = false; | |
923 if (TREE_CODE (arg) != SSA_NAME) | |
924 DUMP_AND_RETURN ("phi arg is not SSA_NAME."); | |
925 if (!check_retval_uses (arg, phi)) | |
926 DUMP_AND_RETURN ("phi arg has uses outside phi" | |
927 " and comparisons against 0.") | |
928 | |
929 gimple *arg_def = SSA_NAME_DEF_STMT (arg); | |
930 if (is_a<gphi *> (arg_def)) | |
931 { | |
145 | 932 if (!malloc_candidate_p_1 (fun, arg, phi, ipa, visited)) |
131 | 933 DUMP_AND_RETURN ("nested phi fail") |
934 continue; | |
935 } | |
936 | |
937 gcall *call_stmt = dyn_cast<gcall *> (arg_def); | |
938 if (!call_stmt) | |
939 DUMP_AND_RETURN ("phi arg is a not a call_stmt.") | |
940 | |
941 tree callee_decl = gimple_call_fndecl (call_stmt); | |
942 if (!callee_decl) | |
943 return false; | |
944 if (!ipa && !DECL_IS_MALLOC (callee_decl)) | |
945 DUMP_AND_RETURN("callee_decl does not have malloc attribute" | |
946 " for non-ipa mode.") | |
947 | |
948 cgraph_edge *cs = node->get_edge (call_stmt); | |
949 if (cs) | |
950 { | |
951 ipa_call_summary *es = ipa_call_summaries->get_create (cs); | |
952 es->is_return_callee_uncaptured = true; | |
953 } | |
954 } | |
955 | |
956 if (all_args_zero) | |
957 DUMP_AND_RETURN ("Return value is a phi with all args equal to 0.") | |
958 } | |
959 | |
960 else | |
961 DUMP_AND_RETURN("def_stmt of return value is not a call or phi-stmt.") | |
962 | |
963 return true; | |
964 } | |
965 | |
966 static bool | |
967 malloc_candidate_p (function *fun, bool ipa) | |
968 { | |
969 basic_block exit_block = EXIT_BLOCK_PTR_FOR_FN (fun); | |
970 edge e; | |
971 edge_iterator ei; | |
972 cgraph_node *node = cgraph_node::get_create (fun->decl); | |
973 | |
974 if (EDGE_COUNT (exit_block->preds) == 0 | |
975 || !flag_delete_null_pointer_checks) | |
976 return false; | |
977 | |
145 | 978 auto_bitmap visited; |
131 | 979 FOR_EACH_EDGE (e, ei, exit_block->preds) |
980 { | |
981 gimple_stmt_iterator gsi = gsi_last_bb (e->src); | |
982 greturn *ret_stmt = dyn_cast<greturn *> (gsi_stmt (gsi)); | |
983 | |
984 if (!ret_stmt) | |
985 return false; | |
986 | |
987 tree retval = gimple_return_retval (ret_stmt); | |
988 if (!retval) | |
989 DUMP_AND_RETURN("No return value.") | |
990 | |
991 if (TREE_CODE (retval) != SSA_NAME | |
992 || TREE_CODE (TREE_TYPE (retval)) != POINTER_TYPE) | |
993 DUMP_AND_RETURN("Return value is not SSA_NAME or not a pointer type.") | |
994 | |
145 | 995 if (!malloc_candidate_p_1 (fun, retval, ret_stmt, ipa, visited)) |
131 | 996 return false; |
997 } | |
998 | |
999 if (dump_file && (dump_flags & TDF_DETAILS)) | |
1000 fprintf (dump_file, "\nFound %s to be candidate for malloc attribute\n", | |
1001 IDENTIFIER_POINTER (DECL_NAME (fun->decl))); | |
1002 return true; | |
1003 } | |
1004 | |
1005 #undef DUMP_AND_RETURN | |
0 | 1006 |
1007 /* This is the main routine for finding the reference patterns for | |
1008 global variables within a function FN. */ | |
1009 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1010 static funct_state |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1011 analyze_function (struct cgraph_node *fn, bool ipa) |
0 | 1012 { |
1013 tree decl = fn->decl; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1014 funct_state l; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1015 basic_block this_block; |
0 | 1016 |
145 | 1017 l = XCNEW (class funct_state_d); |
0 | 1018 l->pure_const_state = IPA_CONST; |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1019 l->state_previously_known = IPA_NEITHER; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1020 l->looping_previously_known = true; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1021 l->looping = false; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1022 l->can_throw = false; |
111 | 1023 l->can_free = false; |
1024 state_from_flags (&l->state_previously_known, &l->looping_previously_known, | |
1025 flags_from_decl_or_type (fn->decl), | |
1026 fn->cannot_return_p ()); | |
1027 | |
1028 if (fn->thunk.thunk_p || fn->alias) | |
1029 { | |
1030 /* Thunk gets propagated through, so nothing interesting happens. */ | |
1031 gcc_assert (ipa); | |
1032 if (fn->thunk.thunk_p && fn->thunk.virtual_offset_p) | |
1033 l->pure_const_state = IPA_NEITHER; | |
1034 return l; | |
1035 } | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1036 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1037 if (dump_file) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1038 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1039 fprintf (dump_file, "\n\n local analysis of %s\n ", |
145 | 1040 fn->dump_name ()); |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1041 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1042 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1043 push_cfun (DECL_STRUCT_FUNCTION (decl)); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1044 |
111 | 1045 FOR_EACH_BB_FN (this_block, cfun) |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1046 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1047 gimple_stmt_iterator gsi; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1048 struct walk_stmt_info wi; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1049 |
111 | 1050 memset (&wi, 0, sizeof (wi)); |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1051 for (gsi = gsi_start_bb (this_block); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1052 !gsi_end_p (gsi); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1053 gsi_next (&gsi)) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1054 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1055 check_stmt (&gsi, l, ipa); |
111 | 1056 if (l->pure_const_state == IPA_NEITHER |
1057 && l->looping | |
1058 && l->can_throw | |
1059 && l->can_free) | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1060 goto end; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1061 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1062 } |
0 | 1063 |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1064 end: |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1065 if (l->pure_const_state != IPA_NEITHER) |
0 | 1066 { |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1067 /* Const functions cannot have back edges (an |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1068 indication of possible infinite loop side |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1069 effect. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1070 if (mark_dfs_back_edges ()) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1071 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1072 /* Preheaders are needed for SCEV to work. |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1073 Simple latches and recorded exits improve chances that loop will |
111 | 1074 proved to be finite in testcases such as in loop-15.c |
1075 and loop-24.c */ | |
1076 loop_optimizer_init (LOOPS_HAVE_PREHEADERS | |
1077 | LOOPS_HAVE_SIMPLE_LATCHES | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1078 | LOOPS_HAVE_RECORDED_EXITS); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1079 if (dump_file && (dump_flags & TDF_DETAILS)) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1080 flow_loops_dump (dump_file, NULL, 0); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1081 if (mark_irreducible_loops ()) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1082 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1083 if (dump_file) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1084 fprintf (dump_file, " has irreducible loops\n"); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1085 l->looping = true; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1086 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1087 else |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1088 { |
145 | 1089 class loop *loop; |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1090 scev_initialize (); |
111 | 1091 FOR_EACH_LOOP (loop, 0) |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1092 if (!finite_loop_p (loop)) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1093 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1094 if (dump_file) |
145 | 1095 fprintf (dump_file, " cannot prove finiteness of " |
111 | 1096 "loop %i\n", loop->num); |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1097 l->looping =true; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1098 break; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1099 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1100 scev_finalize (); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1101 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1102 loop_optimizer_finalize (); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1103 } |
0 | 1104 } |
1105 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1106 if (dump_file && (dump_flags & TDF_DETAILS)) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1107 fprintf (dump_file, " checking previously known:"); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1108 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1109 better_state (&l->pure_const_state, &l->looping, |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1110 l->state_previously_known, |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1111 l->looping_previously_known); |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1112 if (TREE_NOTHROW (decl)) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1113 l->can_throw = false; |
0 | 1114 |
131 | 1115 l->malloc_state = STATE_MALLOC_BOTTOM; |
1116 if (DECL_IS_MALLOC (decl)) | |
1117 l->malloc_state = STATE_MALLOC; | |
1118 else if (ipa && malloc_candidate_p (DECL_STRUCT_FUNCTION (decl), true)) | |
1119 l->malloc_state = STATE_MALLOC_TOP; | |
1120 else if (malloc_candidate_p (DECL_STRUCT_FUNCTION (decl), false)) | |
1121 l->malloc_state = STATE_MALLOC; | |
1122 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1123 pop_cfun (); |
0 | 1124 if (dump_file) |
1125 { | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1126 if (l->looping) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1127 fprintf (dump_file, "Function is locally looping.\n"); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1128 if (l->can_throw) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1129 fprintf (dump_file, "Function is locally throwing.\n"); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1130 if (l->pure_const_state == IPA_CONST) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1131 fprintf (dump_file, "Function is locally const.\n"); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1132 if (l->pure_const_state == IPA_PURE) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1133 fprintf (dump_file, "Function is locally pure.\n"); |
111 | 1134 if (l->can_free) |
1135 fprintf (dump_file, "Function can locally free.\n"); | |
131 | 1136 if (l->malloc_state == STATE_MALLOC) |
1137 fprintf (dump_file, "Function is locally malloc.\n"); | |
0 | 1138 } |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1139 return l; |
0 | 1140 } |
1141 | |
131 | 1142 void |
1143 funct_state_summary_t::insert (cgraph_node *node, funct_state_d *state) | |
0 | 1144 { |
1145 /* There are some shared nodes, in particular the initializers on | |
1146 static declarations. We do not need to scan them more than once | |
1147 since all we would be interested in are the addressof | |
1148 operations. */ | |
111 | 1149 if (opt_for_fn (node->decl, flag_ipa_pure_const)) |
0 | 1150 { |
131 | 1151 funct_state_d *a = analyze_function (node, true); |
1152 new (state) funct_state_d (*a); | |
1153 free (a); | |
0 | 1154 } |
1155 } | |
1156 | |
1157 /* Called when new clone is inserted to callgraph late. */ | |
1158 | |
131 | 1159 void |
1160 funct_state_summary_t::duplicate (cgraph_node *, cgraph_node *, | |
1161 funct_state_d *src_data, | |
1162 funct_state_d *dst_data) | |
0 | 1163 { |
131 | 1164 new (dst_data) funct_state_d (*src_data); |
0 | 1165 } |
1166 | |
1167 | |
111 | 1168 void |
1169 pass_ipa_pure_const:: | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1170 register_hooks (void) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1171 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1172 if (init_p) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1173 return; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1174 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1175 init_p = true; |
0 | 1176 |
131 | 1177 funct_state_summaries = new funct_state_summary_t (symtab); |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1178 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1179 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1180 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1181 /* Analyze each function in the cgraph to see if it is locally PURE or |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1182 CONST. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1183 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1184 static void |
111 | 1185 pure_const_generate_summary (void) |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1186 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1187 struct cgraph_node *node; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1188 |
111 | 1189 pass_ipa_pure_const *pass = static_cast <pass_ipa_pure_const *> (current_pass); |
1190 pass->register_hooks (); | |
0 | 1191 |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1192 /* Process all of the functions. |
0 | 1193 |
145 | 1194 We process AVAIL_INTERPOSABLE functions. We cannot use the results |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1195 by default, but the info can be used at LTO with -fwhole-program or |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1196 when function got cloned and the clone is AVAILABLE. */ |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1197 |
111 | 1198 FOR_EACH_DEFINED_FUNCTION (node) |
1199 if (opt_for_fn (node->decl, flag_ipa_pure_const)) | |
131 | 1200 { |
1201 funct_state_d *a = analyze_function (node, true); | |
1202 new (funct_state_summaries->get_create (node)) funct_state_d (*a); | |
1203 free (a); | |
1204 } | |
0 | 1205 } |
1206 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1207 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1208 /* Serialize the ipa info for lto. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1209 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1210 static void |
111 | 1211 pure_const_write_summary (void) |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1212 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1213 struct cgraph_node *node; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1214 struct lto_simple_output_block *ob |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1215 = lto_create_simple_output_block (LTO_section_ipa_pure_const); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1216 unsigned int count = 0; |
111 | 1217 lto_symtab_encoder_iterator lsei; |
1218 lto_symtab_encoder_t encoder; | |
1219 | |
1220 encoder = lto_get_out_decl_state ()->symtab_node_encoder; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1221 |
111 | 1222 for (lsei = lsei_start_function_in_partition (encoder); !lsei_end_p (lsei); |
1223 lsei_next_function_in_partition (&lsei)) | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1224 { |
111 | 1225 node = lsei_cgraph_node (lsei); |
131 | 1226 if (node->definition && funct_state_summaries->exists (node)) |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1227 count++; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1228 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1229 |
111 | 1230 streamer_write_uhwi_stream (ob->main_stream, count); |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1231 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1232 /* Process all of the functions. */ |
111 | 1233 for (lsei = lsei_start_function_in_partition (encoder); !lsei_end_p (lsei); |
1234 lsei_next_function_in_partition (&lsei)) | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1235 { |
111 | 1236 node = lsei_cgraph_node (lsei); |
131 | 1237 funct_state_d *fs = funct_state_summaries->get (node); |
1238 if (node->definition && fs != NULL) | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1239 { |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1240 struct bitpack_d bp; |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1241 int node_ref; |
111 | 1242 lto_symtab_encoder_t encoder; |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1243 |
111 | 1244 encoder = ob->decl_state->symtab_node_encoder; |
1245 node_ref = lto_symtab_encoder_encode (encoder, node); | |
1246 streamer_write_uhwi_stream (ob->main_stream, node_ref); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1247 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1248 /* Note that flags will need to be read in the opposite |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1249 order as we are pushing the bitflags into FLAGS. */ |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1250 bp = bitpack_create (ob->main_stream); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1251 bp_pack_value (&bp, fs->pure_const_state, 2); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1252 bp_pack_value (&bp, fs->state_previously_known, 2); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1253 bp_pack_value (&bp, fs->looping_previously_known, 1); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1254 bp_pack_value (&bp, fs->looping, 1); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1255 bp_pack_value (&bp, fs->can_throw, 1); |
111 | 1256 bp_pack_value (&bp, fs->can_free, 1); |
131 | 1257 bp_pack_value (&bp, fs->malloc_state, 2); |
111 | 1258 streamer_write_bitpack (&bp); |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1259 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1260 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1261 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1262 lto_destroy_simple_output_block (ob); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1263 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1264 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1265 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1266 /* Deserialize the ipa info for lto. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1267 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1268 static void |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1269 pure_const_read_summary (void) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1270 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1271 struct lto_file_decl_data **file_data_vec = lto_get_file_decl_data (); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1272 struct lto_file_decl_data *file_data; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1273 unsigned int j = 0; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1274 |
111 | 1275 pass_ipa_pure_const *pass = static_cast <pass_ipa_pure_const *> (current_pass); |
1276 pass->register_hooks (); | |
1277 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1278 while ((file_data = file_data_vec[j++])) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1279 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1280 const char *data; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1281 size_t len; |
145 | 1282 class lto_input_block *ib |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1283 = lto_create_simple_input_block (file_data, |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1284 LTO_section_ipa_pure_const, |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1285 &data, &len); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1286 if (ib) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1287 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1288 unsigned int i; |
111 | 1289 unsigned int count = streamer_read_uhwi (ib); |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1290 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1291 for (i = 0; i < count; i++) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1292 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1293 unsigned int index; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1294 struct cgraph_node *node; |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1295 struct bitpack_d bp; |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1296 funct_state fs; |
111 | 1297 lto_symtab_encoder_t encoder; |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1298 |
111 | 1299 index = streamer_read_uhwi (ib); |
1300 encoder = file_data->symtab_node_encoder; | |
1301 node = dyn_cast<cgraph_node *> (lto_symtab_encoder_deref (encoder, | |
1302 index)); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1303 |
131 | 1304 fs = funct_state_summaries->get_create (node); |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1305 /* Note that the flags must be read in the opposite |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1306 order in which they were written (the bitflags were |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1307 pushed into FLAGS). */ |
111 | 1308 bp = streamer_read_bitpack (ib); |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1309 fs->pure_const_state |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1310 = (enum pure_const_state_e) bp_unpack_value (&bp, 2); |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1311 fs->state_previously_known |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1312 = (enum pure_const_state_e) bp_unpack_value (&bp, 2); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1313 fs->looping_previously_known = bp_unpack_value (&bp, 1); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1314 fs->looping = bp_unpack_value (&bp, 1); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1315 fs->can_throw = bp_unpack_value (&bp, 1); |
111 | 1316 fs->can_free = bp_unpack_value (&bp, 1); |
131 | 1317 fs->malloc_state |
1318 = (enum malloc_state_e) bp_unpack_value (&bp, 2); | |
1319 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1320 if (dump_file) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1321 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1322 int flags = flags_from_decl_or_type (node->decl); |
111 | 1323 fprintf (dump_file, "Read info for %s ", node->dump_name ()); |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1324 if (flags & ECF_CONST) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1325 fprintf (dump_file, " const"); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1326 if (flags & ECF_PURE) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1327 fprintf (dump_file, " pure"); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1328 if (flags & ECF_NOTHROW) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1329 fprintf (dump_file, " nothrow"); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1330 fprintf (dump_file, "\n pure const state: %s\n", |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1331 pure_const_names[fs->pure_const_state]); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1332 fprintf (dump_file, " previously known state: %s\n", |
111 | 1333 pure_const_names[fs->state_previously_known]); |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1334 if (fs->looping) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1335 fprintf (dump_file," function is locally looping\n"); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1336 if (fs->looping_previously_known) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1337 fprintf (dump_file," function is previously known looping\n"); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1338 if (fs->can_throw) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1339 fprintf (dump_file," function is locally throwing\n"); |
111 | 1340 if (fs->can_free) |
1341 fprintf (dump_file," function can locally free\n"); | |
131 | 1342 fprintf (dump_file, "\n malloc state: %s\n", |
1343 malloc_state_names[fs->malloc_state]); | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1344 } |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1345 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1346 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1347 lto_destroy_simple_input_block (file_data, |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1348 LTO_section_ipa_pure_const, |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1349 ib, data, len); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1350 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1351 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1352 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1353 |
111 | 1354 /* We only propagate across edges that can throw externally and their callee |
1355 is not interposable. */ | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1356 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1357 static bool |
111 | 1358 ignore_edge_for_nothrow (struct cgraph_edge *e) |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1359 { |
111 | 1360 if (!e->can_throw_external || TREE_NOTHROW (e->callee->decl)) |
1361 return true; | |
1362 | |
1363 enum availability avail; | |
145 | 1364 cgraph_node *ultimate_target |
1365 = e->callee->function_or_virtual_thunk_symbol (&avail, e->caller); | |
1366 if (avail <= AVAIL_INTERPOSABLE || TREE_NOTHROW (ultimate_target->decl)) | |
111 | 1367 return true; |
145 | 1368 return ((opt_for_fn (e->callee->decl, flag_non_call_exceptions) |
1369 && !e->callee->binds_to_current_def_p (e->caller)) | |
1370 || !opt_for_fn (e->caller->decl, flag_ipa_pure_const) | |
1371 || !opt_for_fn (ultimate_target->decl, flag_ipa_pure_const)); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1372 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1373 |
111 | 1374 /* Return true if NODE is self recursive function. |
1375 Indirectly recursive functions appears as non-trivial strongly | |
1376 connected components, so we need to care about self recursion | |
1377 only. */ | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1378 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1379 static bool |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1380 self_recursive_p (struct cgraph_node *node) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1381 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1382 struct cgraph_edge *e; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1383 for (e = node->callees; e; e = e->next_callee) |
111 | 1384 if (e->callee->function_symbol () == node) |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1385 return true; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1386 return false; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1387 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1388 |
111 | 1389 /* Return true if N is cdtor that is not const or pure. In this case we may |
1390 need to remove unreachable function if it is marked const/pure. */ | |
1391 | |
1392 static bool | |
1393 cdtor_p (cgraph_node *n, void *) | |
1394 { | |
1395 if (DECL_STATIC_CONSTRUCTOR (n->decl) || DECL_STATIC_DESTRUCTOR (n->decl)) | |
1396 return ((!TREE_READONLY (n->decl) && !DECL_PURE_P (n->decl)) | |
1397 || DECL_LOOPING_CONST_OR_PURE_P (n->decl)); | |
1398 return false; | |
1399 } | |
1400 | |
145 | 1401 /* Skip edges from and to nodes without ipa_pure_const enabled. |
1402 Ignore not available symbols. */ | |
111 | 1403 |
1404 static bool | |
1405 ignore_edge_for_pure_const (struct cgraph_edge *e) | |
1406 { | |
1407 enum availability avail; | |
145 | 1408 cgraph_node *ultimate_target |
1409 = e->callee->function_or_virtual_thunk_symbol (&avail, e->caller); | |
1410 | |
1411 return (avail <= AVAIL_INTERPOSABLE | |
1412 || !opt_for_fn (e->caller->decl, flag_ipa_pure_const) | |
1413 || !opt_for_fn (ultimate_target->decl, | |
1414 flag_ipa_pure_const)); | |
111 | 1415 } |
1416 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1417 /* Produce transitive closure over the callgraph and compute pure/const |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1418 attributes. */ |
0 | 1419 |
111 | 1420 static bool |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1421 propagate_pure_const (void) |
0 | 1422 { |
1423 struct cgraph_node *node; | |
1424 struct cgraph_node *w; | |
1425 struct cgraph_node **order = | |
111 | 1426 XCNEWVEC (struct cgraph_node *, symtab->cgraph_count); |
0 | 1427 int order_pos; |
1428 int i; | |
1429 struct ipa_dfs_info * w_info; | |
111 | 1430 bool remove_p = false; |
1431 bool has_cdtor; | |
0 | 1432 |
145 | 1433 order_pos = ipa_reduced_postorder (order, true, |
111 | 1434 ignore_edge_for_pure_const); |
0 | 1435 if (dump_file) |
1436 { | |
111 | 1437 cgraph_node::dump_cgraph (dump_file); |
1438 ipa_print_order (dump_file, "reduced", order, order_pos); | |
0 | 1439 } |
1440 | |
111 | 1441 /* Propagate the local information through the call graph to produce |
0 | 1442 the global information. All the nodes within a cycle will have |
1443 the same info so we collapse cycles first. Then we can do the | |
1444 propagation in one pass from the leaves to the roots. */ | |
1445 for (i = 0; i < order_pos; i++ ) | |
1446 { | |
1447 enum pure_const_state_e pure_const_state = IPA_CONST; | |
1448 bool looping = false; | |
1449 int count = 0; | |
1450 node = order[i]; | |
1451 | |
111 | 1452 if (node->alias) |
1453 continue; | |
1454 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1455 if (dump_file && (dump_flags & TDF_DETAILS)) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1456 fprintf (dump_file, "Starting cycle\n"); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1457 |
0 | 1458 /* Find the worst state for any node in the cycle. */ |
1459 w = node; | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1460 while (w && pure_const_state != IPA_NEITHER) |
0 | 1461 { |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1462 struct cgraph_edge *e; |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1463 struct cgraph_edge *ie; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1464 int i; |
111 | 1465 struct ipa_ref *ref = NULL; |
0 | 1466 |
131 | 1467 funct_state w_l = funct_state_summaries->get_create (w); |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1468 if (dump_file && (dump_flags & TDF_DETAILS)) |
111 | 1469 fprintf (dump_file, " Visiting %s state:%s looping %i\n", |
1470 w->dump_name (), | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1471 pure_const_names[w_l->pure_const_state], |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1472 w_l->looping); |
0 | 1473 |
111 | 1474 /* First merge in function body properties. |
1475 We are safe to pass NULL as FROM and TO because we will take care | |
1476 of possible interposition when walking callees. */ | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1477 worse_state (&pure_const_state, &looping, |
111 | 1478 w_l->pure_const_state, w_l->looping, |
1479 NULL, NULL); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1480 if (pure_const_state == IPA_NEITHER) |
0 | 1481 break; |
1482 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1483 count++; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1484 |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1485 /* We consider recursive cycles as possibly infinite. |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1486 This might be relaxed since infinite recursion leads to stack |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1487 overflow. */ |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1488 if (count > 1) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1489 looping = true; |
0 | 1490 |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1491 /* Now walk the edges and merge in callee properties. */ |
111 | 1492 for (e = w->callees; e && pure_const_state != IPA_NEITHER; |
1493 e = e->next_callee) | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1494 { |
111 | 1495 enum availability avail; |
1496 struct cgraph_node *y = e->callee-> | |
1497 function_or_virtual_thunk_symbol (&avail, | |
1498 e->caller); | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1499 enum pure_const_state_e edge_state = IPA_CONST; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1500 bool edge_looping = false; |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1501 |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1502 if (dump_file && (dump_flags & TDF_DETAILS)) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1503 { |
111 | 1504 fprintf (dump_file, " Call to %s", |
1505 e->callee->dump_name ()); | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1506 } |
111 | 1507 if (avail > AVAIL_INTERPOSABLE) |
0 | 1508 { |
145 | 1509 funct_state y_l = funct_state_summaries->get_create (y); |
1510 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1511 if (dump_file && (dump_flags & TDF_DETAILS)) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1512 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1513 fprintf (dump_file, |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1514 " state:%s looping:%i\n", |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1515 pure_const_names[y_l->pure_const_state], |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1516 y_l->looping); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1517 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1518 if (y_l->pure_const_state > IPA_PURE |
111 | 1519 && e->cannot_lead_to_return_p ()) |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1520 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1521 if (dump_file && (dump_flags & TDF_DETAILS)) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1522 fprintf (dump_file, |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1523 " Ignoring side effects" |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1524 " -> pure, looping\n"); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1525 edge_state = IPA_PURE; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1526 edge_looping = true; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1527 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1528 else |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1529 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1530 edge_state = y_l->pure_const_state; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1531 edge_looping = y_l->looping; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1532 } |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1533 } |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1534 else if (special_builtin_state (&edge_state, &edge_looping, |
145 | 1535 y->decl)) |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1536 ; |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1537 else |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1538 state_from_flags (&edge_state, &edge_looping, |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1539 flags_from_decl_or_type (y->decl), |
111 | 1540 e->cannot_lead_to_return_p ()); |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1541 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1542 /* Merge the results with what we already know. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1543 better_state (&edge_state, &edge_looping, |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1544 w_l->state_previously_known, |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1545 w_l->looping_previously_known); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1546 worse_state (&pure_const_state, &looping, |
111 | 1547 edge_state, edge_looping, e->caller, e->callee); |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1548 if (pure_const_state == IPA_NEITHER) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1549 break; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1550 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1551 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1552 /* Now process the indirect call. */ |
111 | 1553 for (ie = w->indirect_calls; |
1554 ie && pure_const_state != IPA_NEITHER; ie = ie->next_callee) | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1555 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1556 enum pure_const_state_e edge_state = IPA_CONST; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1557 bool edge_looping = false; |
0 | 1558 |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1559 if (dump_file && (dump_flags & TDF_DETAILS)) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1560 fprintf (dump_file, " Indirect call"); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1561 state_from_flags (&edge_state, &edge_looping, |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1562 ie->indirect_info->ecf_flags, |
111 | 1563 ie->cannot_lead_to_return_p ()); |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1564 /* Merge the results with what we already know. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1565 better_state (&edge_state, &edge_looping, |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1566 w_l->state_previously_known, |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1567 w_l->looping_previously_known); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1568 worse_state (&pure_const_state, &looping, |
111 | 1569 edge_state, edge_looping, NULL, NULL); |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1570 if (pure_const_state == IPA_NEITHER) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1571 break; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1572 } |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1573 |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1574 /* And finally all loads and stores. */ |
111 | 1575 for (i = 0; w->iterate_reference (i, ref) |
1576 && pure_const_state != IPA_NEITHER; i++) | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1577 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1578 enum pure_const_state_e ref_state = IPA_CONST; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1579 bool ref_looping = false; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1580 switch (ref->use) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1581 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1582 case IPA_REF_LOAD: |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1583 /* readonly reads are safe. */ |
111 | 1584 if (TREE_READONLY (ref->referred->decl)) |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1585 break; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1586 if (dump_file && (dump_flags & TDF_DETAILS)) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1587 fprintf (dump_file, " nonreadonly global var read\n"); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1588 ref_state = IPA_PURE; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1589 break; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1590 case IPA_REF_STORE: |
111 | 1591 if (ref->cannot_lead_to_return ()) |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1592 break; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1593 ref_state = IPA_NEITHER; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1594 if (dump_file && (dump_flags & TDF_DETAILS)) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1595 fprintf (dump_file, " global var write\n"); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1596 break; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1597 case IPA_REF_ADDR: |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1598 break; |
111 | 1599 default: |
1600 gcc_unreachable (); | |
0 | 1601 } |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1602 better_state (&ref_state, &ref_looping, |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1603 w_l->state_previously_known, |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1604 w_l->looping_previously_known); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1605 worse_state (&pure_const_state, &looping, |
111 | 1606 ref_state, ref_looping, NULL, NULL); |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1607 if (pure_const_state == IPA_NEITHER) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1608 break; |
0 | 1609 } |
1610 w_info = (struct ipa_dfs_info *) w->aux; | |
1611 w = w_info->next_cycle; | |
1612 } | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1613 if (dump_file && (dump_flags & TDF_DETAILS)) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1614 fprintf (dump_file, "Result %s looping %i\n", |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1615 pure_const_names [pure_const_state], |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1616 looping); |
0 | 1617 |
111 | 1618 /* Find the worst state of can_free for any node in the cycle. */ |
1619 bool can_free = false; | |
1620 w = node; | |
1621 while (w && !can_free) | |
1622 { | |
1623 struct cgraph_edge *e; | |
131 | 1624 funct_state w_l = funct_state_summaries->get (w); |
111 | 1625 |
1626 if (w_l->can_free | |
1627 || w->get_availability () == AVAIL_INTERPOSABLE | |
1628 || w->indirect_calls) | |
1629 can_free = true; | |
1630 | |
1631 for (e = w->callees; e && !can_free; e = e->next_callee) | |
1632 { | |
1633 enum availability avail; | |
1634 struct cgraph_node *y = e->callee-> | |
1635 function_or_virtual_thunk_symbol (&avail, | |
1636 e->caller); | |
1637 | |
1638 if (avail > AVAIL_INTERPOSABLE) | |
131 | 1639 can_free = funct_state_summaries->get (y)->can_free; |
111 | 1640 else |
1641 can_free = true; | |
1642 } | |
1643 w_info = (struct ipa_dfs_info *) w->aux; | |
1644 w = w_info->next_cycle; | |
1645 } | |
1646 | |
0 | 1647 /* Copy back the region's pure_const_state which is shared by |
1648 all nodes in the region. */ | |
1649 w = node; | |
1650 while (w) | |
1651 { | |
131 | 1652 funct_state w_l = funct_state_summaries->get (w); |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1653 enum pure_const_state_e this_state = pure_const_state; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1654 bool this_looping = looping; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1655 |
111 | 1656 w_l->can_free = can_free; |
1657 w->nonfreeing_fn = !can_free; | |
1658 if (!can_free && dump_file) | |
1659 fprintf (dump_file, "Function found not to call free: %s\n", | |
145 | 1660 w->dump_name ()); |
111 | 1661 |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1662 if (w_l->state_previously_known != IPA_NEITHER |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1663 && this_state > w_l->state_previously_known) |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1664 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1665 this_state = w_l->state_previously_known; |
111 | 1666 if (this_state == IPA_NEITHER) |
1667 this_looping = w_l->looping_previously_known; | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1668 } |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1669 if (!this_looping && self_recursive_p (w)) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1670 this_looping = true; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1671 if (!w_l->looping_previously_known) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1672 this_looping = false; |
0 | 1673 |
1674 /* All nodes within a cycle share the same info. */ | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1675 w_l->pure_const_state = this_state; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1676 w_l->looping = this_looping; |
0 | 1677 |
111 | 1678 /* Inline clones share declaration with their offline copies; |
1679 do not modify their declarations since the offline copy may | |
1680 be different. */ | |
145 | 1681 if (!w->inlined_to) |
111 | 1682 switch (this_state) |
1683 { | |
1684 case IPA_CONST: | |
1685 if (!TREE_READONLY (w->decl)) | |
1686 { | |
1687 warn_function_const (w->decl, !this_looping); | |
1688 if (dump_file) | |
1689 fprintf (dump_file, "Function found to be %sconst: %s\n", | |
1690 this_looping ? "looping " : "", | |
145 | 1691 w->dump_name ()); |
111 | 1692 } |
1693 /* Turning constructor or destructor to non-looping const/pure | |
1694 enables us to possibly remove the function completely. */ | |
1695 if (this_looping) | |
1696 has_cdtor = false; | |
1697 else | |
1698 has_cdtor = w->call_for_symbol_and_aliases (cdtor_p, | |
1699 NULL, true); | |
1700 if (w->set_const_flag (true, this_looping)) | |
1701 { | |
1702 if (dump_file) | |
1703 fprintf (dump_file, | |
1704 "Declaration updated to be %sconst: %s\n", | |
1705 this_looping ? "looping " : "", | |
145 | 1706 w->dump_name ()); |
111 | 1707 remove_p |= has_cdtor; |
1708 } | |
1709 break; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1710 |
111 | 1711 case IPA_PURE: |
1712 if (!DECL_PURE_P (w->decl)) | |
1713 { | |
1714 warn_function_pure (w->decl, !this_looping); | |
1715 if (dump_file) | |
1716 fprintf (dump_file, "Function found to be %spure: %s\n", | |
1717 this_looping ? "looping " : "", | |
145 | 1718 w->dump_name ()); |
111 | 1719 } |
1720 if (this_looping) | |
1721 has_cdtor = false; | |
1722 else | |
1723 has_cdtor = w->call_for_symbol_and_aliases (cdtor_p, | |
1724 NULL, true); | |
1725 if (w->set_pure_flag (true, this_looping)) | |
1726 { | |
1727 if (dump_file) | |
1728 fprintf (dump_file, | |
1729 "Declaration updated to be %spure: %s\n", | |
1730 this_looping ? "looping " : "", | |
145 | 1731 w->dump_name ()); |
111 | 1732 remove_p |= has_cdtor; |
1733 } | |
1734 break; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1735 |
111 | 1736 default: |
1737 break; | |
1738 } | |
0 | 1739 w_info = (struct ipa_dfs_info *) w->aux; |
1740 w = w_info->next_cycle; | |
1741 } | |
1742 } | |
1743 | |
111 | 1744 ipa_free_postorder_info (); |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1745 free (order); |
111 | 1746 return remove_p; |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1747 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1748 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1749 /* Produce transitive closure over the callgraph and compute nothrow |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1750 attributes. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1751 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1752 static void |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1753 propagate_nothrow (void) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1754 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1755 struct cgraph_node *node; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1756 struct cgraph_node *w; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1757 struct cgraph_node **order = |
111 | 1758 XCNEWVEC (struct cgraph_node *, symtab->cgraph_count); |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1759 int order_pos; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1760 int i; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1761 struct ipa_dfs_info * w_info; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1762 |
145 | 1763 order_pos = ipa_reduced_postorder (order, true, |
111 | 1764 ignore_edge_for_nothrow); |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1765 if (dump_file) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1766 { |
111 | 1767 cgraph_node::dump_cgraph (dump_file); |
1768 ipa_print_order (dump_file, "reduced for nothrow", order, order_pos); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1769 } |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1770 |
111 | 1771 /* Propagate the local information through the call graph to produce |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1772 the global information. All the nodes within a cycle will have |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1773 the same info so we collapse cycles first. Then we can do the |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1774 propagation in one pass from the leaves to the roots. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1775 for (i = 0; i < order_pos; i++ ) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1776 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1777 bool can_throw = false; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1778 node = order[i]; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1779 |
111 | 1780 if (node->alias) |
1781 continue; | |
1782 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1783 /* Find the worst state for any node in the cycle. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1784 w = node; |
111 | 1785 while (w && !can_throw) |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1786 { |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1787 struct cgraph_edge *e, *ie; |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1788 |
111 | 1789 if (!TREE_NOTHROW (w->decl)) |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1790 { |
131 | 1791 funct_state w_l = funct_state_summaries->get_create (w); |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1792 |
111 | 1793 if (w_l->can_throw |
1794 || w->get_availability () == AVAIL_INTERPOSABLE) | |
1795 can_throw = true; | |
1796 | |
1797 for (e = w->callees; e && !can_throw; e = e->next_callee) | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1798 { |
111 | 1799 enum availability avail; |
1800 | |
1801 if (!e->can_throw_external || TREE_NOTHROW (e->callee->decl)) | |
1802 continue; | |
1803 | |
1804 struct cgraph_node *y = e->callee-> | |
1805 function_or_virtual_thunk_symbol (&avail, | |
1806 e->caller); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1807 |
145 | 1808 /* We can use info about the callee only if we know it |
1809 cannot be interposed. | |
111 | 1810 When callee is compiled with non-call exceptions we also |
1811 must check that the declaration is bound to current | |
1812 body as other semantically equivalent body may still | |
1813 throw. */ | |
1814 if (avail <= AVAIL_INTERPOSABLE | |
1815 || (!TREE_NOTHROW (y->decl) | |
131 | 1816 && (funct_state_summaries->get_create (y)->can_throw |
111 | 1817 || (opt_for_fn (y->decl, flag_non_call_exceptions) |
1818 && !e->callee->binds_to_current_def_p (w))))) | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1819 can_throw = true; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1820 } |
111 | 1821 for (ie = w->indirect_calls; ie && !can_throw; |
1822 ie = ie->next_callee) | |
1823 if (ie->can_throw_external | |
1824 && !(ie->indirect_info->ecf_flags & ECF_NOTHROW)) | |
1825 can_throw = true; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1826 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1827 w_info = (struct ipa_dfs_info *) w->aux; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1828 w = w_info->next_cycle; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1829 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1830 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1831 /* Copy back the region's pure_const_state which is shared by |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1832 all nodes in the region. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1833 w = node; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1834 while (w) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1835 { |
131 | 1836 funct_state w_l = funct_state_summaries->get_create (w); |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1837 if (!can_throw && !TREE_NOTHROW (w->decl)) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1838 { |
111 | 1839 /* Inline clones share declaration with their offline copies; |
1840 do not modify their declarations since the offline copy may | |
1841 be different. */ | |
145 | 1842 if (!w->inlined_to) |
111 | 1843 { |
1844 w->set_nothrow_flag (true); | |
1845 if (dump_file) | |
1846 fprintf (dump_file, "Function found to be nothrow: %s\n", | |
145 | 1847 w->dump_name ()); |
111 | 1848 } |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1849 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1850 else if (can_throw && !TREE_NOTHROW (w->decl)) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1851 w_l->can_throw = true; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1852 w_info = (struct ipa_dfs_info *) w->aux; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1853 w = w_info->next_cycle; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1854 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1855 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1856 |
111 | 1857 ipa_free_postorder_info (); |
0 | 1858 free (order); |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1859 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1860 |
131 | 1861 /* Debugging function to dump state of malloc lattice. */ |
1862 | |
1863 DEBUG_FUNCTION | |
1864 static void | |
1865 dump_malloc_lattice (FILE *dump_file, const char *s) | |
1866 { | |
1867 if (!dump_file) | |
1868 return; | |
1869 | |
1870 fprintf (dump_file, "\n\nMALLOC LATTICE %s:\n", s); | |
1871 cgraph_node *node; | |
1872 FOR_EACH_FUNCTION (node) | |
1873 { | |
1874 funct_state fs = funct_state_summaries->get (node); | |
1875 if (fs) | |
145 | 1876 fprintf (dump_file, "%s: %s\n", node->dump_name (), |
131 | 1877 malloc_state_names[fs->malloc_state]); |
1878 } | |
1879 } | |
1880 | |
1881 /* Propagate malloc attribute across the callgraph. */ | |
1882 | |
1883 static void | |
1884 propagate_malloc (void) | |
1885 { | |
1886 cgraph_node *node; | |
1887 FOR_EACH_FUNCTION (node) | |
1888 { | |
1889 if (DECL_IS_MALLOC (node->decl)) | |
1890 if (!funct_state_summaries->exists (node)) | |
1891 { | |
1892 funct_state fs = funct_state_summaries->get_create (node); | |
1893 fs->malloc_state = STATE_MALLOC; | |
1894 } | |
1895 } | |
1896 | |
1897 dump_malloc_lattice (dump_file, "Initial"); | |
1898 struct cgraph_node **order | |
1899 = XNEWVEC (struct cgraph_node *, symtab->cgraph_count); | |
1900 int order_pos = ipa_reverse_postorder (order); | |
1901 bool changed = true; | |
1902 | |
1903 while (changed) | |
1904 { | |
1905 changed = false; | |
1906 /* Walk in postorder. */ | |
1907 for (int i = order_pos - 1; i >= 0; --i) | |
1908 { | |
1909 cgraph_node *node = order[i]; | |
1910 if (node->alias | |
1911 || !node->definition | |
1912 || !funct_state_summaries->exists (node)) | |
1913 continue; | |
1914 | |
1915 funct_state l = funct_state_summaries->get (node); | |
1916 | |
1917 /* FIXME: add support for indirect-calls. */ | |
1918 if (node->indirect_calls) | |
1919 { | |
1920 l->malloc_state = STATE_MALLOC_BOTTOM; | |
1921 continue; | |
1922 } | |
1923 | |
1924 if (node->get_availability () <= AVAIL_INTERPOSABLE) | |
1925 { | |
1926 l->malloc_state = STATE_MALLOC_BOTTOM; | |
1927 continue; | |
1928 } | |
1929 | |
1930 if (l->malloc_state == STATE_MALLOC_BOTTOM) | |
1931 continue; | |
1932 | |
1933 vec<cgraph_node *> callees = vNULL; | |
1934 for (cgraph_edge *cs = node->callees; cs; cs = cs->next_callee) | |
1935 { | |
1936 ipa_call_summary *es = ipa_call_summaries->get_create (cs); | |
1937 if (es && es->is_return_callee_uncaptured) | |
1938 callees.safe_push (cs->callee); | |
1939 } | |
1940 | |
1941 malloc_state_e new_state = l->malloc_state; | |
1942 for (unsigned j = 0; j < callees.length (); j++) | |
1943 { | |
1944 cgraph_node *callee = callees[j]; | |
1945 if (!funct_state_summaries->exists (node)) | |
1946 { | |
1947 new_state = STATE_MALLOC_BOTTOM; | |
1948 break; | |
1949 } | |
1950 malloc_state_e callee_state | |
1951 = funct_state_summaries->get_create (callee)->malloc_state; | |
1952 if (new_state < callee_state) | |
1953 new_state = callee_state; | |
1954 } | |
1955 if (new_state != l->malloc_state) | |
1956 { | |
1957 changed = true; | |
1958 l->malloc_state = new_state; | |
1959 } | |
1960 } | |
1961 } | |
1962 | |
1963 FOR_EACH_DEFINED_FUNCTION (node) | |
1964 if (funct_state_summaries->exists (node)) | |
1965 { | |
1966 funct_state l = funct_state_summaries->get (node); | |
1967 if (!node->alias | |
1968 && l->malloc_state == STATE_MALLOC | |
145 | 1969 && !node->inlined_to) |
131 | 1970 { |
1971 if (dump_file && (dump_flags & TDF_DETAILS)) | |
1972 fprintf (dump_file, "Function %s found to be malloc\n", | |
145 | 1973 node->dump_name ()); |
131 | 1974 |
1975 bool malloc_decl_p = DECL_IS_MALLOC (node->decl); | |
1976 node->set_malloc_flag (true); | |
1977 if (!malloc_decl_p && warn_suggest_attribute_malloc) | |
1978 warn_function_malloc (node->decl); | |
1979 } | |
1980 } | |
1981 | |
1982 dump_malloc_lattice (dump_file, "after propagation"); | |
1983 ipa_free_postorder_info (); | |
1984 free (order); | |
1985 } | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1986 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1987 /* Produce the global information by preforming a transitive closure |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1988 on the local information that was produced by generate_summary. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1989 |
111 | 1990 unsigned int |
1991 pass_ipa_pure_const:: | |
1992 execute (function *) | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1993 { |
111 | 1994 bool remove_p; |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1995 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1996 /* Nothrow makes more function to not lead to return and improve |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1997 later analysis. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1998 propagate_nothrow (); |
131 | 1999 propagate_malloc (); |
111 | 2000 remove_p = propagate_pure_const (); |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2001 |
131 | 2002 delete funct_state_summaries; |
111 | 2003 return remove_p ? TODO_remove_functions : 0; |
0 | 2004 } |
2005 | |
2006 static bool | |
2007 gate_pure_const (void) | |
2008 { | |
111 | 2009 return flag_ipa_pure_const || in_lto_p; |
0 | 2010 } |
2011 | |
111 | 2012 pass_ipa_pure_const::pass_ipa_pure_const(gcc::context *ctxt) |
2013 : ipa_opt_pass_d(pass_data_ipa_pure_const, ctxt, | |
2014 pure_const_generate_summary, /* generate_summary */ | |
2015 pure_const_write_summary, /* write_summary */ | |
2016 pure_const_read_summary, /* read_summary */ | |
2017 NULL, /* write_optimization_summary */ | |
2018 NULL, /* read_optimization_summary */ | |
2019 NULL, /* stmt_fixup */ | |
2020 0, /* function_transform_todo_flags_start */ | |
2021 NULL, /* function_transform */ | |
2022 NULL), /* variable_transform */ | |
131 | 2023 init_p (false) {} |
111 | 2024 |
2025 ipa_opt_pass_d * | |
2026 make_pass_ipa_pure_const (gcc::context *ctxt) | |
2027 { | |
2028 return new pass_ipa_pure_const (ctxt); | |
2029 } | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2030 |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2031 /* Return true if function should be skipped for local pure const analysis. */ |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2032 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2033 static bool |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2034 skip_function_for_local_pure_const (struct cgraph_node *node) |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2035 { |
111 | 2036 /* Because we do not schedule pass_fixup_cfg over whole program after early |
2037 optimizations we must not promote functions that are called by already | |
2038 processed functions. */ | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2039 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2040 if (function_called_by_processed_nodes_p ()) |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2041 { |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2042 if (dump_file) |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2043 fprintf (dump_file, "Function called in recursive cycle; ignoring\n"); |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2044 return true; |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2045 } |
111 | 2046 /* Save some work and do not analyze functions which are interposable and |
2047 do not have any non-interposable aliases. */ | |
2048 if (node->get_availability () <= AVAIL_INTERPOSABLE | |
2049 && !node->has_aliases_p ()) | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2050 { |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2051 if (dump_file) |
111 | 2052 fprintf (dump_file, |
2053 "Function is interposable; not analyzing.\n"); | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2054 return true; |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2055 } |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2056 return false; |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2057 } |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2058 |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2059 /* Simple local pass for pure const discovery reusing the analysis from |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2060 ipa_pure_const. This pass is effective when executed together with |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2061 other optimization passes in early optimization pass queue. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2062 |
111 | 2063 namespace { |
2064 | |
2065 const pass_data pass_data_local_pure_const = | |
2066 { | |
2067 GIMPLE_PASS, /* type */ | |
2068 "local-pure-const", /* name */ | |
2069 OPTGROUP_NONE, /* optinfo_flags */ | |
2070 TV_IPA_PURE_CONST, /* tv_id */ | |
2071 0, /* properties_required */ | |
2072 0, /* properties_provided */ | |
2073 0, /* properties_destroyed */ | |
2074 0, /* todo_flags_start */ | |
2075 0, /* todo_flags_finish */ | |
2076 }; | |
2077 | |
2078 class pass_local_pure_const : public gimple_opt_pass | |
2079 { | |
2080 public: | |
2081 pass_local_pure_const (gcc::context *ctxt) | |
2082 : gimple_opt_pass (pass_data_local_pure_const, ctxt) | |
2083 {} | |
2084 | |
2085 /* opt_pass methods: */ | |
2086 opt_pass * clone () { return new pass_local_pure_const (m_ctxt); } | |
2087 virtual bool gate (function *) { return gate_pure_const (); } | |
2088 virtual unsigned int execute (function *); | |
2089 | |
2090 }; // class pass_local_pure_const | |
2091 | |
2092 unsigned int | |
2093 pass_local_pure_const::execute (function *fun) | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2094 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2095 bool changed = false; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2096 funct_state l; |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2097 bool skip; |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2098 struct cgraph_node *node; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2099 |
111 | 2100 node = cgraph_node::get (current_function_decl); |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2101 skip = skip_function_for_local_pure_const (node); |
111 | 2102 |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2103 if (!warn_suggest_attribute_const |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2104 && !warn_suggest_attribute_pure |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2105 && skip) |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2106 return 0; |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2107 |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2108 l = analyze_function (node, false); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2109 |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2110 /* Do NORETURN discovery. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2111 if (!skip && !TREE_THIS_VOLATILE (current_function_decl) |
111 | 2112 && EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (fun)->preds) == 0) |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2113 { |
111 | 2114 warn_function_noreturn (fun->decl); |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2115 if (dump_file) |
111 | 2116 fprintf (dump_file, "Function found to be noreturn: %s\n", |
2117 current_function_name ()); | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2118 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2119 /* Update declaration and reduce profile to executed once. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2120 TREE_THIS_VOLATILE (current_function_decl) = 1; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2121 if (node->frequency > NODE_FREQUENCY_EXECUTED_ONCE) |
111 | 2122 node->frequency = NODE_FREQUENCY_EXECUTED_ONCE; |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2123 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2124 changed = true; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2125 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2126 |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2127 switch (l->pure_const_state) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2128 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2129 case IPA_CONST: |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2130 if (!TREE_READONLY (current_function_decl)) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2131 { |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2132 warn_function_const (current_function_decl, !l->looping); |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2133 if (dump_file) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2134 fprintf (dump_file, "Function found to be %sconst: %s\n", |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2135 l->looping ? "looping " : "", |
111 | 2136 current_function_name ()); |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2137 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2138 else if (DECL_LOOPING_CONST_OR_PURE_P (current_function_decl) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2139 && !l->looping) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2140 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2141 if (dump_file) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2142 fprintf (dump_file, "Function found to be non-looping: %s\n", |
111 | 2143 current_function_name ()); |
2144 } | |
2145 if (!skip && node->set_const_flag (true, l->looping)) | |
2146 { | |
2147 if (dump_file) | |
2148 fprintf (dump_file, "Declaration updated to be %sconst: %s\n", | |
2149 l->looping ? "looping " : "", | |
2150 current_function_name ()); | |
2151 changed = true; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2152 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2153 break; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2154 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2155 case IPA_PURE: |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2156 if (!DECL_PURE_P (current_function_decl)) |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2157 { |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2158 warn_function_pure (current_function_decl, !l->looping); |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2159 if (dump_file) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2160 fprintf (dump_file, "Function found to be %spure: %s\n", |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2161 l->looping ? "looping " : "", |
111 | 2162 current_function_name ()); |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2163 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2164 else if (DECL_LOOPING_CONST_OR_PURE_P (current_function_decl) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2165 && !l->looping) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2166 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2167 if (dump_file) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2168 fprintf (dump_file, "Function found to be non-looping: %s\n", |
111 | 2169 current_function_name ()); |
2170 } | |
2171 if (!skip && node->set_pure_flag (true, l->looping)) | |
2172 { | |
2173 if (dump_file) | |
2174 fprintf (dump_file, "Declaration updated to be %spure: %s\n", | |
2175 l->looping ? "looping " : "", | |
2176 current_function_name ()); | |
2177 changed = true; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2178 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2179 break; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2180 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2181 default: |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2182 break; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2183 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2184 if (!l->can_throw && !TREE_NOTHROW (current_function_decl)) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2185 { |
111 | 2186 node->set_nothrow_flag (true); |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2187 changed = true; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2188 if (dump_file) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2189 fprintf (dump_file, "Function found to be nothrow: %s\n", |
111 | 2190 current_function_name ()); |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2191 } |
131 | 2192 |
2193 if (l->malloc_state == STATE_MALLOC | |
2194 && !DECL_IS_MALLOC (current_function_decl)) | |
2195 { | |
2196 node->set_malloc_flag (true); | |
2197 if (warn_suggest_attribute_malloc) | |
2198 warn_function_malloc (node->decl); | |
2199 changed = true; | |
2200 if (dump_file) | |
2201 fprintf (dump_file, "Function found to be malloc: %s\n", | |
145 | 2202 node->dump_name ()); |
131 | 2203 } |
2204 | |
111 | 2205 free (l); |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2206 if (changed) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2207 return execute_fixup_cfg (); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2208 else |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2209 return 0; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2210 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2211 |
111 | 2212 } // anon namespace |
2213 | |
2214 gimple_opt_pass * | |
2215 make_pass_local_pure_const (gcc::context *ctxt) | |
2216 { | |
2217 return new pass_local_pure_const (ctxt); | |
2218 } | |
2219 | |
2220 /* Emit noreturn warnings. */ | |
2221 | |
2222 namespace { | |
2223 | |
2224 const pass_data pass_data_warn_function_noreturn = | |
2225 { | |
2226 GIMPLE_PASS, /* type */ | |
2227 "*warn_function_noreturn", /* name */ | |
2228 OPTGROUP_NONE, /* optinfo_flags */ | |
2229 TV_NONE, /* tv_id */ | |
2230 PROP_cfg, /* properties_required */ | |
2231 0, /* properties_provided */ | |
2232 0, /* properties_destroyed */ | |
2233 0, /* todo_flags_start */ | |
2234 0, /* todo_flags_finish */ | |
2235 }; | |
2236 | |
2237 class pass_warn_function_noreturn : public gimple_opt_pass | |
2238 { | |
2239 public: | |
2240 pass_warn_function_noreturn (gcc::context *ctxt) | |
2241 : gimple_opt_pass (pass_data_warn_function_noreturn, ctxt) | |
2242 {} | |
2243 | |
2244 /* opt_pass methods: */ | |
2245 virtual bool gate (function *) { return warn_suggest_attribute_noreturn; } | |
2246 virtual unsigned int execute (function *fun) | |
2247 { | |
2248 if (!TREE_THIS_VOLATILE (current_function_decl) | |
2249 && EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (fun)->preds) == 0) | |
2250 warn_function_noreturn (current_function_decl); | |
2251 return 0; | |
2252 } | |
2253 | |
2254 }; // class pass_warn_function_noreturn | |
2255 | |
2256 } // anon namespace | |
2257 | |
2258 gimple_opt_pass * | |
2259 make_pass_warn_function_noreturn (gcc::context *ctxt) | |
2260 { | |
2261 return new pass_warn_function_noreturn (ctxt); | |
2262 } | |
2263 | |
2264 /* Simple local pass for pure const discovery reusing the analysis from | |
2265 ipa_pure_const. This pass is effective when executed together with | |
2266 other optimization passes in early optimization pass queue. */ | |
2267 | |
2268 namespace { | |
2269 | |
2270 const pass_data pass_data_nothrow = | |
2271 { | |
2272 GIMPLE_PASS, /* type */ | |
2273 "nothrow", /* name */ | |
2274 OPTGROUP_NONE, /* optinfo_flags */ | |
2275 TV_IPA_PURE_CONST, /* tv_id */ | |
2276 0, /* properties_required */ | |
2277 0, /* properties_provided */ | |
2278 0, /* properties_destroyed */ | |
2279 0, /* todo_flags_start */ | |
2280 0, /* todo_flags_finish */ | |
2281 }; | |
2282 | |
2283 class pass_nothrow : public gimple_opt_pass | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2284 { |
111 | 2285 public: |
2286 pass_nothrow (gcc::context *ctxt) | |
2287 : gimple_opt_pass (pass_data_nothrow, ctxt) | |
2288 {} | |
2289 | |
2290 /* opt_pass methods: */ | |
2291 opt_pass * clone () { return new pass_nothrow (m_ctxt); } | |
2292 virtual bool gate (function *) { return optimize; } | |
2293 virtual unsigned int execute (function *); | |
2294 | |
2295 }; // class pass_nothrow | |
2296 | |
2297 unsigned int | |
2298 pass_nothrow::execute (function *) | |
2299 { | |
2300 struct cgraph_node *node; | |
2301 basic_block this_block; | |
2302 | |
2303 if (TREE_NOTHROW (current_function_decl)) | |
2304 return 0; | |
2305 | |
2306 node = cgraph_node::get (current_function_decl); | |
2307 | |
145 | 2308 /* We run during lowering, we cannot really use availability yet. */ |
111 | 2309 if (cgraph_node::get (current_function_decl)->get_availability () |
2310 <= AVAIL_INTERPOSABLE) | |
2311 { | |
2312 if (dump_file) | |
2313 fprintf (dump_file, "Function is interposable;" | |
2314 " not analyzing.\n"); | |
2315 return true; | |
2316 } | |
2317 | |
2318 FOR_EACH_BB_FN (this_block, cfun) | |
2319 { | |
2320 for (gimple_stmt_iterator gsi = gsi_start_bb (this_block); | |
2321 !gsi_end_p (gsi); | |
2322 gsi_next (&gsi)) | |
131 | 2323 if (stmt_can_throw_external (cfun, gsi_stmt (gsi))) |
111 | 2324 { |
2325 if (is_gimple_call (gsi_stmt (gsi))) | |
2326 { | |
2327 tree callee_t = gimple_call_fndecl (gsi_stmt (gsi)); | |
2328 if (callee_t && recursive_call_p (current_function_decl, | |
2329 callee_t)) | |
2330 continue; | |
2331 } | |
2332 | |
2333 if (dump_file) | |
2334 { | |
2335 fprintf (dump_file, "Statement can throw: "); | |
2336 print_gimple_stmt (dump_file, gsi_stmt (gsi), 0); | |
2337 } | |
2338 return 0; | |
2339 } | |
2340 } | |
2341 | |
2342 node->set_nothrow_flag (true); | |
2343 | |
2344 bool cfg_changed = false; | |
2345 if (self_recursive_p (node)) | |
2346 FOR_EACH_BB_FN (this_block, cfun) | |
2347 if (gimple *g = last_stmt (this_block)) | |
2348 if (is_gimple_call (g)) | |
2349 { | |
2350 tree callee_t = gimple_call_fndecl (g); | |
2351 if (callee_t | |
2352 && recursive_call_p (current_function_decl, callee_t) | |
2353 && maybe_clean_eh_stmt (g) | |
2354 && gimple_purge_dead_eh_edges (this_block)) | |
2355 cfg_changed = true; | |
2356 } | |
2357 | |
2358 if (dump_file) | |
2359 fprintf (dump_file, "Function found to be nothrow: %s\n", | |
2360 current_function_name ()); | |
2361 return cfg_changed ? TODO_cleanup_cfg : 0; | |
2362 } | |
2363 | |
2364 } // anon namespace | |
2365 | |
2366 gimple_opt_pass * | |
2367 make_pass_nothrow (gcc::context *ctxt) | |
2368 { | |
2369 return new pass_nothrow (ctxt); | |
2370 } |