comparison gcc/ipa-pure-const.c @ 63:b7f97abdc517 gcc-4.6-20100522

update gcc from gcc-4.5.0 to gcc-4.6
author ryoma <e075725@ie.u-ryukyu.ac.jp>
date Mon, 24 May 2010 12:47:05 +0900
parents 77e2b8dfacca
children f6334be47118
comparison
equal deleted inserted replaced
56:3c8a44c06a95 63:b7f97abdc517
1 /* Callgraph based analysis of static variables. 1 /* Callgraph based analysis of static variables.
2 Copyright (C) 2004, 2005, 2007, 2008, 2009 Free Software Foundation, Inc. 2 Copyright (C) 2004, 2005, 2007, 2008, 2009, 2010
3 Free Software Foundation, Inc.
3 Contributed by Kenneth Zadeck <zadeck@naturalbridge.com> 4 Contributed by Kenneth Zadeck <zadeck@naturalbridge.com>
4 5
5 This file is part of GCC. 6 This file is part of GCC.
6 7
7 GCC is free software; you can redistribute it and/or modify it under 8 GCC is free software; you can redistribute it and/or modify it under
46 #include "gimple.h" 47 #include "gimple.h"
47 #include "cgraph.h" 48 #include "cgraph.h"
48 #include "output.h" 49 #include "output.h"
49 #include "flags.h" 50 #include "flags.h"
50 #include "timevar.h" 51 #include "timevar.h"
52 #include "toplev.h"
51 #include "diagnostic.h" 53 #include "diagnostic.h"
54 #include "gimple-pretty-print.h"
52 #include "langhooks.h" 55 #include "langhooks.h"
53 #include "target.h" 56 #include "target.h"
54 #include "lto-streamer.h" 57 #include "lto-streamer.h"
55 #include "cfgloop.h" 58 #include "cfgloop.h"
56 #include "tree-scalar-evolution.h" 59 #include "tree-scalar-evolution.h"
60 #include "intl.h"
61 #include "opts.h"
57 62
58 static struct pointer_set_t *visited_nodes; 63 static struct pointer_set_t *visited_nodes;
59 64
60 /* Lattice values for const and pure functions. Everything starts out 65 /* Lattice values for const and pure functions. Everything starts out
61 being const, then may drop to pure and then neither depending on 66 being const, then may drop to pure and then neither depending on
103 /* Holders of ipa cgraph hooks: */ 108 /* Holders of ipa cgraph hooks: */
104 static struct cgraph_node_hook_list *function_insertion_hook_holder; 109 static struct cgraph_node_hook_list *function_insertion_hook_holder;
105 static struct cgraph_2node_hook_list *node_duplication_hook_holder; 110 static struct cgraph_2node_hook_list *node_duplication_hook_holder;
106 static struct cgraph_node_hook_list *node_removal_hook_holder; 111 static struct cgraph_node_hook_list *node_removal_hook_holder;
107 112
113 /* Try to guess if function body will always be visible to compiler
114 when compiling the call and whether compiler will be able
115 to propagate the information by itself. */
116
117 static bool
118 function_always_visible_to_compiler_p (tree decl)
119 {
120 return (!TREE_PUBLIC (decl) || DECL_DECLARED_INLINE_P (decl));
121 }
122
123 /* Emit suggestion about attribute ATTRIB_NAME for DECL. KNOWN_FINITE
124 is true if the function is known to be finite. The diagnostic is
125 controlled by OPTION. WARNED_ABOUT is a pointer_set unique for
126 OPTION, this function may initialize it and it is always returned
127 by the function. */
128
129 static struct pointer_set_t *
130 suggest_attribute (int option, tree decl, bool known_finite,
131 struct pointer_set_t *warned_about,
132 const char * attrib_name)
133 {
134 if (!option_enabled (option))
135 return warned_about;
136 if (TREE_THIS_VOLATILE (decl)
137 || (known_finite && function_always_visible_to_compiler_p (decl)))
138 return warned_about;
139
140 if (!warned_about)
141 warned_about = pointer_set_create ();
142 if (pointer_set_contains (warned_about, decl))
143 return warned_about;
144 pointer_set_insert (warned_about, decl);
145 warning_at (DECL_SOURCE_LOCATION (decl),
146 option,
147 known_finite
148 ? _("function might be candidate for attribute %<%s%>")
149 : _("function might be candidate for attribute %<%s%>"
150 " if it is known to return normally"), attrib_name);
151 return warned_about;
152 }
153
154 /* Emit suggestion about __attribute_((pure)) for DECL. KNOWN_FINITE
155 is true if the function is known to be finite. */
156
157 static void
158 warn_function_pure (tree decl, bool known_finite)
159 {
160 static struct pointer_set_t *warned_about;
161
162 warned_about
163 = suggest_attribute (OPT_Wsuggest_attribute_pure, decl,
164 known_finite, warned_about, "pure");
165 }
166
167 /* Emit suggestion about __attribute_((const)) for DECL. KNOWN_FINITE
168 is true if the function is known to be finite. */
169
170 static void
171 warn_function_const (tree decl, bool known_finite)
172 {
173 static struct pointer_set_t *warned_about;
174 warned_about
175 = suggest_attribute (OPT_Wsuggest_attribute_const, decl,
176 known_finite, warned_about, "const");
177 }
108 /* Init the function state. */ 178 /* Init the function state. */
109 179
110 static void 180 static void
111 finish_state (void) 181 finish_state (void)
112 { 182 {
157 if (!TREE_STATIC (t) && !DECL_EXTERNAL (t)) 227 if (!TREE_STATIC (t) && !DECL_EXTERNAL (t))
158 return; 228 return;
159 229
160 /* If the variable has the "used" attribute, treat it as if it had a 230 /* If the variable has the "used" attribute, treat it as if it had a
161 been touched by the devil. */ 231 been touched by the devil. */
162 if (lookup_attribute ("used", DECL_ATTRIBUTES (t))) 232 if (DECL_PRESERVE_P (t))
163 { 233 {
164 local->pure_const_state = IPA_NEITHER; 234 local->pure_const_state = IPA_NEITHER;
165 if (dump_file) 235 if (dump_file)
166 fprintf (dump_file, " Used static/global variable is not const/pure\n"); 236 fprintf (dump_file, " Used static/global variable is not const/pure\n");
167 return; 237 return;
322 } 392 }
323 } 393 }
324 394
325 /* When not in IPA mode, we can still handle self recursion. */ 395 /* When not in IPA mode, we can still handle self recursion. */
326 if (!ipa && callee_t == current_function_decl) 396 if (!ipa && callee_t == current_function_decl)
327 local->looping = true; 397 {
398 if (dump_file)
399 fprintf (dump_file, " Recursive call can loop.\n");
400 local->looping = true;
401 }
328 /* Either calle is unknown or we are doing local analysis. 402 /* Either calle is unknown or we are doing local analysis.
329 Look to see if there are any bits available for the callee (such as by 403 Look to see if there are any bits available for the callee (such as by
330 declaration or because it is builtin) and process solely on the basis of 404 declaration or because it is builtin) and process solely on the basis of
331 those bits. */ 405 those bits. */
332 else if (!ipa || !callee_t) 406 else if (!ipa || !callee_t)
350 local->can_throw = true; 424 local->can_throw = true;
351 } 425 }
352 if (flags & ECF_CONST) 426 if (flags & ECF_CONST)
353 { 427 {
354 if (callee_t && DECL_LOOPING_CONST_OR_PURE_P (callee_t)) 428 if (callee_t && DECL_LOOPING_CONST_OR_PURE_P (callee_t))
355 local->looping = true; 429 {
430 if (dump_file)
431 fprintf (dump_file, " calls looping pure.\n");
432 local->looping = true;
433 }
356 } 434 }
357 else if (flags & ECF_PURE) 435 else if (flags & ECF_PURE)
358 { 436 {
359 if (callee_t && DECL_LOOPING_CONST_OR_PURE_P (callee_t)) 437 if (callee_t && DECL_LOOPING_CONST_OR_PURE_P (callee_t))
360 local->looping = true; 438 {
439 if (dump_file)
440 fprintf (dump_file, " calls looping const.\n");
441 local->looping = true;
442 }
361 if (dump_file) 443 if (dump_file)
362 fprintf (dump_file, " pure function call in not const\n"); 444 fprintf (dump_file, " pure function call in not const\n");
363 if (local->pure_const_state == IPA_CONST) 445 if (local->pure_const_state == IPA_CONST)
364 local->pure_const_state = IPA_PURE; 446 local->pure_const_state = IPA_PURE;
365 } 447 }
450 break; 532 break;
451 case GIMPLE_ASM: 533 case GIMPLE_ASM:
452 for (i = 0; i < gimple_asm_nclobbers (stmt); i++) 534 for (i = 0; i < gimple_asm_nclobbers (stmt); i++)
453 { 535 {
454 tree op = gimple_asm_clobber_op (stmt, i); 536 tree op = gimple_asm_clobber_op (stmt, i);
455 if (simple_cst_equal(TREE_VALUE (op), memory_identifier_string) == 1) 537 if (strcmp (TREE_STRING_POINTER (TREE_VALUE (op)), "memory") == 0)
456 { 538 {
457 if (dump_file) 539 if (dump_file)
458 fprintf (dump_file, " memory asm clobber is not const/pure"); 540 fprintf (dump_file, " memory asm clobber is not const/pure");
459 /* Abandon all hope, ye who enter here. */ 541 /* Abandon all hope, ye who enter here. */
460 local->pure_const_state = IPA_NEITHER; 542 local->pure_const_state = IPA_NEITHER;
601 /* There are some shared nodes, in particular the initializers on 683 /* There are some shared nodes, in particular the initializers on
602 static declarations. We do not need to scan them more than once 684 static declarations. We do not need to scan them more than once
603 since all we would be interested in are the addressof 685 since all we would be interested in are the addressof
604 operations. */ 686 operations. */
605 visited_nodes = pointer_set_create (); 687 visited_nodes = pointer_set_create ();
606 set_function_state (node, analyze_function (node, true)); 688 if (cgraph_function_body_availability (node) > AVAIL_OVERWRITABLE)
689 set_function_state (node, analyze_function (node, true));
607 pointer_set_destroy (visited_nodes); 690 pointer_set_destroy (visited_nodes);
608 visited_nodes = NULL; 691 visited_nodes = NULL;
609 } 692 }
610 693
611 /* Called when new clone is inserted to callgraph late. */ 694 /* Called when new clone is inserted to callgraph late. */
687 770
688 771
689 /* Serialize the ipa info for lto. */ 772 /* Serialize the ipa info for lto. */
690 773
691 static void 774 static void
692 pure_const_write_summary (cgraph_node_set set) 775 pure_const_write_summary (cgraph_node_set set,
776 varpool_node_set vset ATTRIBUTE_UNUSED)
693 { 777 {
694 struct cgraph_node *node; 778 struct cgraph_node *node;
695 struct lto_simple_output_block *ob 779 struct lto_simple_output_block *ob
696 = lto_create_simple_output_block (LTO_section_ipa_pure_const); 780 = lto_create_simple_output_block (LTO_section_ipa_pure_const);
697 unsigned int count = 0; 781 unsigned int count = 0;
935 w_l->looping = this_looping; 1019 w_l->looping = this_looping;
936 1020
937 switch (this_state) 1021 switch (this_state)
938 { 1022 {
939 case IPA_CONST: 1023 case IPA_CONST:
940 if (!TREE_READONLY (w->decl) && dump_file) 1024 if (!TREE_READONLY (w->decl))
941 fprintf (dump_file, "Function found to be %sconst: %s\n", 1025 {
942 this_looping ? "looping " : "", 1026 warn_function_const (w->decl, !this_looping);
943 cgraph_node_name (w)); 1027 if (dump_file)
1028 fprintf (dump_file, "Function found to be %sconst: %s\n",
1029 this_looping ? "looping " : "",
1030 cgraph_node_name (w));
1031 }
944 cgraph_set_readonly_flag (w, true); 1032 cgraph_set_readonly_flag (w, true);
945 cgraph_set_looping_const_or_pure_flag (w, this_looping); 1033 cgraph_set_looping_const_or_pure_flag (w, this_looping);
946 break; 1034 break;
947 1035
948 case IPA_PURE: 1036 case IPA_PURE:
949 if (!DECL_PURE_P (w->decl) && dump_file) 1037 if (!DECL_PURE_P (w->decl))
950 fprintf (dump_file, "Function found to be %spure: %s\n", 1038 {
951 this_looping ? "looping " : "", 1039 warn_function_pure (w->decl, !this_looping);
952 cgraph_node_name (w)); 1040 if (dump_file)
1041 fprintf (dump_file, "Function found to be %spure: %s\n",
1042 this_looping ? "looping " : "",
1043 cgraph_node_name (w));
1044 }
953 cgraph_set_pure_flag (w, true); 1045 cgraph_set_pure_flag (w, true);
954 cgraph_set_looping_const_or_pure_flag (w, this_looping); 1046 cgraph_set_looping_const_or_pure_flag (w, this_looping);
955 break; 1047 break;
956 1048
957 default: 1049 default:
1092 0 /* todo_flags_finish */ 1184 0 /* todo_flags_finish */
1093 }, 1185 },
1094 generate_summary, /* generate_summary */ 1186 generate_summary, /* generate_summary */
1095 pure_const_write_summary, /* write_summary */ 1187 pure_const_write_summary, /* write_summary */
1096 pure_const_read_summary, /* read_summary */ 1188 pure_const_read_summary, /* read_summary */
1097 NULL, /* function_read_summary */ 1189 NULL, /* write_optimization_summary */
1190 NULL, /* read_optimization_summary */
1098 NULL, /* stmt_fixup */ 1191 NULL, /* stmt_fixup */
1099 0, /* TODOs */ 1192 0, /* TODOs */
1100 NULL, /* function_transform */ 1193 NULL, /* function_transform */
1101 NULL /* variable_transform */ 1194 NULL /* variable_transform */
1102 }; 1195 };
1103 1196
1197 /* Return true if function should be skipped for local pure const analysis. */
1198
1199 static bool
1200 skip_function_for_local_pure_const (struct cgraph_node *node)
1201 {
1202 /* Because we do not schedule pass_fixup_cfg over whole program after early optimizations
1203 we must not promote functions that are called by already processed functions. */
1204
1205 if (function_called_by_processed_nodes_p ())
1206 {
1207 if (dump_file)
1208 fprintf (dump_file, "Function called in recursive cycle; ignoring\n");
1209 return true;
1210 }
1211 if (cgraph_function_body_availability (node) <= AVAIL_OVERWRITABLE)
1212 {
1213 if (dump_file)
1214 fprintf (dump_file, "Function is not available or overwrittable; not analyzing.\n");
1215 return true;
1216 }
1217 return false;
1218 }
1219
1104 /* Simple local pass for pure const discovery reusing the analysis from 1220 /* Simple local pass for pure const discovery reusing the analysis from
1105 ipa_pure_const. This pass is effective when executed together with 1221 ipa_pure_const. This pass is effective when executed together with
1106 other optimization passes in early optimization pass queue. */ 1222 other optimization passes in early optimization pass queue. */
1107 1223
1108 static unsigned int 1224 static unsigned int
1109 local_pure_const (void) 1225 local_pure_const (void)
1110 { 1226 {
1111 bool changed = false; 1227 bool changed = false;
1112 funct_state l; 1228 funct_state l;
1229 bool skip;
1113 struct cgraph_node *node; 1230 struct cgraph_node *node;
1114 1231
1115 /* Because we do not schedule pass_fixup_cfg over whole program after early optimizations
1116 we must not promote functions that are called by already processed functions. */
1117
1118 if (function_called_by_processed_nodes_p ())
1119 {
1120 if (dump_file)
1121 fprintf (dump_file, "Function called in recursive cycle; ignoring\n");
1122 return 0;
1123 }
1124 node = cgraph_node (current_function_decl); 1232 node = cgraph_node (current_function_decl);
1125 if (cgraph_function_body_availability (node) <= AVAIL_OVERWRITABLE) 1233 skip = skip_function_for_local_pure_const (node);
1126 { 1234 if (!warn_suggest_attribute_const
1127 if (dump_file) 1235 && !warn_suggest_attribute_pure
1128 fprintf (dump_file, "Function has wrong visibility; ignoring\n"); 1236 && skip)
1129 return 0; 1237 return 0;
1130 }
1131
1132 l = analyze_function (node, false); 1238 l = analyze_function (node, false);
1133 1239
1134 switch (l->pure_const_state) 1240 switch (l->pure_const_state)
1135 { 1241 {
1136 case IPA_CONST: 1242 case IPA_CONST:
1137 if (!TREE_READONLY (current_function_decl)) 1243 if (!TREE_READONLY (current_function_decl))
1138 { 1244 {
1139 cgraph_set_readonly_flag (node, true); 1245 warn_function_const (current_function_decl, !l->looping);
1140 cgraph_set_looping_const_or_pure_flag (node, l->looping); 1246 if (!skip)
1141 changed = true; 1247 {
1248 cgraph_set_readonly_flag (node, true);
1249 cgraph_set_looping_const_or_pure_flag (node, l->looping);
1250 changed = true;
1251 }
1142 if (dump_file) 1252 if (dump_file)
1143 fprintf (dump_file, "Function found to be %sconst: %s\n", 1253 fprintf (dump_file, "Function found to be %sconst: %s\n",
1144 l->looping ? "looping " : "", 1254 l->looping ? "looping " : "",
1145 lang_hooks.decl_printable_name (current_function_decl, 1255 lang_hooks.decl_printable_name (current_function_decl,
1146 2)); 1256 2));
1147 } 1257 }
1148 else if (DECL_LOOPING_CONST_OR_PURE_P (current_function_decl) 1258 else if (DECL_LOOPING_CONST_OR_PURE_P (current_function_decl)
1149 && !l->looping) 1259 && !l->looping)
1150 { 1260 {
1151 cgraph_set_looping_const_or_pure_flag (node, false); 1261 if (!skip)
1152 changed = true; 1262 {
1263 cgraph_set_looping_const_or_pure_flag (node, false);
1264 changed = true;
1265 }
1153 if (dump_file) 1266 if (dump_file)
1154 fprintf (dump_file, "Function found to be non-looping: %s\n", 1267 fprintf (dump_file, "Function found to be non-looping: %s\n",
1155 lang_hooks.decl_printable_name (current_function_decl, 1268 lang_hooks.decl_printable_name (current_function_decl,
1156 2)); 1269 2));
1157 } 1270 }
1158 break; 1271 break;
1159 1272
1160 case IPA_PURE: 1273 case IPA_PURE:
1161 if (!TREE_READONLY (current_function_decl)) 1274 if (!DECL_PURE_P (current_function_decl))
1162 { 1275 {
1163 cgraph_set_pure_flag (node, true); 1276 if (!skip)
1164 cgraph_set_looping_const_or_pure_flag (node, l->looping); 1277 {
1165 changed = true; 1278 cgraph_set_pure_flag (node, true);
1279 cgraph_set_looping_const_or_pure_flag (node, l->looping);
1280 changed = true;
1281 }
1282 warn_function_pure (current_function_decl, !l->looping);
1166 if (dump_file) 1283 if (dump_file)
1167 fprintf (dump_file, "Function found to be %spure: %s\n", 1284 fprintf (dump_file, "Function found to be %spure: %s\n",
1168 l->looping ? "looping " : "", 1285 l->looping ? "looping " : "",
1169 lang_hooks.decl_printable_name (current_function_decl, 1286 lang_hooks.decl_printable_name (current_function_decl,
1170 2)); 1287 2));
1171 } 1288 }
1172 else if (DECL_LOOPING_CONST_OR_PURE_P (current_function_decl) 1289 else if (DECL_LOOPING_CONST_OR_PURE_P (current_function_decl)
1173 && !l->looping) 1290 && !l->looping)
1174 { 1291 {
1175 cgraph_set_looping_const_or_pure_flag (node, false); 1292 if (!skip)
1176 changed = true; 1293 {
1294 cgraph_set_looping_const_or_pure_flag (node, false);
1295 changed = true;
1296 }
1177 if (dump_file) 1297 if (dump_file)
1178 fprintf (dump_file, "Function found to be non-looping: %s\n", 1298 fprintf (dump_file, "Function found to be non-looping: %s\n",
1179 lang_hooks.decl_printable_name (current_function_decl, 1299 lang_hooks.decl_printable_name (current_function_decl,
1180 2)); 1300 2));
1181 } 1301 }