Mercurial > hg > CbC > CbC_gcc
comparison gcc/ipa-pure-const.c @ 67:f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
author | nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Tue, 22 Mar 2011 17:18:12 +0900 |
parents | b7f97abdc517 |
children | 04ced10e8804 |
comparison
equal
deleted
inserted
replaced
65:65488c3d617d | 67:f6334be47118 |
---|---|
47 #include "gimple.h" | 47 #include "gimple.h" |
48 #include "cgraph.h" | 48 #include "cgraph.h" |
49 #include "output.h" | 49 #include "output.h" |
50 #include "flags.h" | 50 #include "flags.h" |
51 #include "timevar.h" | 51 #include "timevar.h" |
52 #include "toplev.h" | |
53 #include "diagnostic.h" | 52 #include "diagnostic.h" |
54 #include "gimple-pretty-print.h" | 53 #include "gimple-pretty-print.h" |
55 #include "langhooks.h" | 54 #include "langhooks.h" |
56 #include "target.h" | 55 #include "target.h" |
57 #include "lto-streamer.h" | 56 #include "lto-streamer.h" |
70 IPA_CONST, | 69 IPA_CONST, |
71 IPA_PURE, | 70 IPA_PURE, |
72 IPA_NEITHER | 71 IPA_NEITHER |
73 }; | 72 }; |
74 | 73 |
74 const char *pure_const_names[3] = {"const", "pure", "neither"}; | |
75 | |
75 /* Holder for the const_state. There is one of these per function | 76 /* Holder for the const_state. There is one of these per function |
76 decl. */ | 77 decl. */ |
77 struct funct_state_d | 78 struct funct_state_d |
78 { | 79 { |
79 /* See above. */ | 80 /* See above. */ |
91 bool looping; | 92 bool looping; |
92 | 93 |
93 bool can_throw; | 94 bool can_throw; |
94 }; | 95 }; |
95 | 96 |
97 /* State used when we know nothing about function. */ | |
98 static struct funct_state_d varying_state | |
99 = { IPA_NEITHER, IPA_NEITHER, true, true, true }; | |
100 | |
101 | |
96 typedef struct funct_state_d * funct_state; | 102 typedef struct funct_state_d * funct_state; |
97 | 103 |
98 /* The storage of the funct_state is abstracted because there is the | 104 /* The storage of the funct_state is abstracted because there is the |
99 possibility that it may be desirable to move this to the cgraph | 105 possibility that it may be desirable to move this to the cgraph |
100 local info. */ | 106 local info. */ |
129 static struct pointer_set_t * | 135 static struct pointer_set_t * |
130 suggest_attribute (int option, tree decl, bool known_finite, | 136 suggest_attribute (int option, tree decl, bool known_finite, |
131 struct pointer_set_t *warned_about, | 137 struct pointer_set_t *warned_about, |
132 const char * attrib_name) | 138 const char * attrib_name) |
133 { | 139 { |
134 if (!option_enabled (option)) | 140 if (!option_enabled (option, &global_options)) |
135 return warned_about; | 141 return warned_about; |
136 if (TREE_THIS_VOLATILE (decl) | 142 if (TREE_THIS_VOLATILE (decl) |
137 || (known_finite && function_always_visible_to_compiler_p (decl))) | 143 || (known_finite && function_always_visible_to_compiler_p (decl))) |
138 return warned_about; | 144 return warned_about; |
139 | 145 |
173 static struct pointer_set_t *warned_about; | 179 static struct pointer_set_t *warned_about; |
174 warned_about | 180 warned_about |
175 = suggest_attribute (OPT_Wsuggest_attribute_const, decl, | 181 = suggest_attribute (OPT_Wsuggest_attribute_const, decl, |
176 known_finite, warned_about, "const"); | 182 known_finite, warned_about, "const"); |
177 } | 183 } |
184 | |
185 void | |
186 warn_function_noreturn (tree decl) | |
187 { | |
188 static struct pointer_set_t *warned_about; | |
189 if (!lang_hooks.missing_noreturn_ok_p (decl)) | |
190 warned_about | |
191 = suggest_attribute (OPT_Wsuggest_attribute_noreturn, decl, | |
192 true, warned_about, "noreturn"); | |
193 } | |
178 /* Init the function state. */ | 194 /* Init the function state. */ |
179 | 195 |
180 static void | 196 static void |
181 finish_state (void) | 197 finish_state (void) |
182 { | 198 { |
183 free (funct_state_vec); | 199 free (funct_state_vec); |
184 } | 200 } |
185 | 201 |
186 | 202 |
203 /* Return true if we have a function state for NODE. */ | |
204 | |
205 static inline bool | |
206 has_function_state (struct cgraph_node *node) | |
207 { | |
208 if (!funct_state_vec | |
209 || VEC_length (funct_state, funct_state_vec) <= (unsigned int)node->uid) | |
210 return false; | |
211 return VEC_index (funct_state, funct_state_vec, node->uid) != NULL; | |
212 } | |
213 | |
187 /* Return the function state from NODE. */ | 214 /* Return the function state from NODE. */ |
188 | 215 |
189 static inline funct_state | 216 static inline funct_state |
190 get_function_state (struct cgraph_node *node) | 217 get_function_state (struct cgraph_node *node) |
191 { | 218 { |
192 if (!funct_state_vec | 219 if (!funct_state_vec |
193 || VEC_length (funct_state, funct_state_vec) <= (unsigned int)node->uid) | 220 || VEC_length (funct_state, funct_state_vec) <= (unsigned int)node->uid |
194 return NULL; | 221 || !VEC_index (funct_state, funct_state_vec, node->uid)) |
195 return VEC_index (funct_state, funct_state_vec, node->uid); | 222 /* We might want to put correct previously_known state into varying. */ |
223 return &varying_state; | |
224 return VEC_index (funct_state, funct_state_vec, node->uid); | |
196 } | 225 } |
197 | 226 |
198 /* Set the function state S for NODE. */ | 227 /* Set the function state S for NODE. */ |
199 | 228 |
200 static inline void | 229 static inline void |
209 /* Check to see if the use (or definition when CHECKING_WRITE is true) | 238 /* Check to see if the use (or definition when CHECKING_WRITE is true) |
210 variable T is legal in a function that is either pure or const. */ | 239 variable T is legal in a function that is either pure or const. */ |
211 | 240 |
212 static inline void | 241 static inline void |
213 check_decl (funct_state local, | 242 check_decl (funct_state local, |
214 tree t, bool checking_write) | 243 tree t, bool checking_write, bool ipa) |
215 { | 244 { |
216 /* Do not want to do anything with volatile except mark any | 245 /* Do not want to do anything with volatile except mark any |
217 function that uses one to be not const or pure. */ | 246 function that uses one to be not const or pure. */ |
218 if (TREE_THIS_VOLATILE (t)) | 247 if (TREE_THIS_VOLATILE (t)) |
219 { | 248 { |
234 local->pure_const_state = IPA_NEITHER; | 263 local->pure_const_state = IPA_NEITHER; |
235 if (dump_file) | 264 if (dump_file) |
236 fprintf (dump_file, " Used static/global variable is not const/pure\n"); | 265 fprintf (dump_file, " Used static/global variable is not const/pure\n"); |
237 return; | 266 return; |
238 } | 267 } |
268 | |
269 /* In IPA mode we are not interested in checking actual loads and stores; | |
270 they will be processed at propagation time using ipa_ref. */ | |
271 if (ipa) | |
272 return; | |
239 | 273 |
240 /* Since we have dealt with the locals and params cases above, if we | 274 /* Since we have dealt with the locals and params cases above, if we |
241 are CHECKING_WRITE, this cannot be a pure or constant | 275 are CHECKING_WRITE, this cannot be a pure or constant |
242 function. */ | 276 function. */ |
243 if (checking_write) | 277 if (checking_write) |
291 if (dump_file) | 325 if (dump_file) |
292 fprintf (dump_file, " Volatile indirect ref is not const/pure\n"); | 326 fprintf (dump_file, " Volatile indirect ref is not const/pure\n"); |
293 return; | 327 return; |
294 } | 328 } |
295 else if (t | 329 else if (t |
296 && INDIRECT_REF_P (t) | 330 && (INDIRECT_REF_P (t) || TREE_CODE (t) == MEM_REF) |
297 && TREE_CODE (TREE_OPERAND (t, 0)) == SSA_NAME | 331 && TREE_CODE (TREE_OPERAND (t, 0)) == SSA_NAME |
298 && !ptr_deref_may_alias_global_p (TREE_OPERAND (t, 0))) | 332 && !ptr_deref_may_alias_global_p (TREE_OPERAND (t, 0))) |
299 { | 333 { |
300 if (dump_file) | 334 if (dump_file) |
301 fprintf (dump_file, " Indirect ref to local memory is OK\n"); | 335 fprintf (dump_file, " Indirect ref to local memory is OK\n"); |
313 if (dump_file) | 347 if (dump_file) |
314 fprintf (dump_file, " Indirect ref read is not const\n"); | 348 fprintf (dump_file, " Indirect ref read is not const\n"); |
315 if (local->pure_const_state == IPA_CONST) | 349 if (local->pure_const_state == IPA_CONST) |
316 local->pure_const_state = IPA_PURE; | 350 local->pure_const_state = IPA_PURE; |
317 } | 351 } |
352 } | |
353 | |
354 /* compute state based on ECF FLAGS and store to STATE and LOOPING. */ | |
355 | |
356 static void | |
357 state_from_flags (enum pure_const_state_e *state, bool *looping, | |
358 int flags, bool cannot_lead_to_return) | |
359 { | |
360 *looping = false; | |
361 if (flags & ECF_LOOPING_CONST_OR_PURE) | |
362 { | |
363 *looping = true; | |
364 if (dump_file && (dump_flags & TDF_DETAILS)) | |
365 fprintf (dump_file, " looping"); | |
366 } | |
367 if (flags & ECF_CONST) | |
368 { | |
369 *state = IPA_CONST; | |
370 if (dump_file && (dump_flags & TDF_DETAILS)) | |
371 fprintf (dump_file, " const\n"); | |
372 } | |
373 else if (flags & ECF_PURE) | |
374 { | |
375 *state = IPA_PURE; | |
376 if (dump_file && (dump_flags & TDF_DETAILS)) | |
377 fprintf (dump_file, " pure\n"); | |
378 } | |
379 else if (cannot_lead_to_return) | |
380 { | |
381 *state = IPA_PURE; | |
382 *looping = true; | |
383 if (dump_file && (dump_flags & TDF_DETAILS)) | |
384 fprintf (dump_file, " ignoring side effects->pure looping\n"); | |
385 } | |
386 else | |
387 { | |
388 if (dump_file && (dump_flags & TDF_DETAILS)) | |
389 fprintf (dump_file, " neihter\n"); | |
390 *state = IPA_NEITHER; | |
391 *looping = true; | |
392 } | |
393 } | |
394 | |
395 /* Merge STATE and STATE2 and LOOPING and LOOPING2 and store | |
396 into STATE and LOOPING better of the two variants. | |
397 Be sure to merge looping correctly. IPA_NEITHER functions | |
398 have looping 0 even if they don't have to return. */ | |
399 | |
400 static inline void | |
401 better_state (enum pure_const_state_e *state, bool *looping, | |
402 enum pure_const_state_e state2, bool looping2) | |
403 { | |
404 if (state2 < *state) | |
405 { | |
406 if (*state == IPA_NEITHER) | |
407 *looping = looping2; | |
408 else | |
409 *looping = MIN (*looping, looping2); | |
410 } | |
411 else if (state2 != IPA_NEITHER) | |
412 *looping = MIN (*looping, looping2); | |
413 } | |
414 | |
415 /* Merge STATE and STATE2 and LOOPING and LOOPING2 and store | |
416 into STATE and LOOPING worse of the two variants. */ | |
417 | |
418 static inline void | |
419 worse_state (enum pure_const_state_e *state, bool *looping, | |
420 enum pure_const_state_e state2, bool looping2) | |
421 { | |
422 *state = MAX (*state, state2); | |
423 *looping = MAX (*looping, looping2); | |
424 } | |
425 | |
426 /* Recognize special cases of builtins that are by themselves not pure or const | |
427 but function using them is. */ | |
428 static bool | |
429 special_builtin_state (enum pure_const_state_e *state, bool *looping, | |
430 tree callee) | |
431 { | |
432 if (DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL) | |
433 switch (DECL_FUNCTION_CODE (callee)) | |
434 { | |
435 case BUILT_IN_RETURN: | |
436 case BUILT_IN_UNREACHABLE: | |
437 case BUILT_IN_ALLOCA: | |
438 case BUILT_IN_STACK_SAVE: | |
439 case BUILT_IN_STACK_RESTORE: | |
440 case BUILT_IN_EH_POINTER: | |
441 case BUILT_IN_EH_FILTER: | |
442 case BUILT_IN_UNWIND_RESUME: | |
443 case BUILT_IN_CXA_END_CLEANUP: | |
444 case BUILT_IN_EH_COPY_VALUES: | |
445 case BUILT_IN_FRAME_ADDRESS: | |
446 case BUILT_IN_APPLY: | |
447 case BUILT_IN_APPLY_ARGS: | |
448 *looping = false; | |
449 *state = IPA_CONST; | |
450 return true; | |
451 case BUILT_IN_PREFETCH: | |
452 *looping = true; | |
453 *state = IPA_CONST; | |
454 return true; | |
455 } | |
456 return false; | |
318 } | 457 } |
319 | 458 |
320 /* Check the parameters of a function call to CALL_EXPR to see if | 459 /* Check the parameters of a function call to CALL_EXPR to see if |
321 there are any references in the parameters that are not allowed for | 460 there are any references in the parameters that are not allowed for |
322 pure or const functions. Also check to see if this is either an | 461 pure or const functions. Also check to see if this is either an |
338 unsigned int i; | 477 unsigned int i; |
339 for (i = 0; i < gimple_num_ops (call); i++) | 478 for (i = 0; i < gimple_num_ops (call); i++) |
340 if (gimple_op (call, i) | 479 if (gimple_op (call, i) |
341 && tree_could_throw_p (gimple_op (call, i))) | 480 && tree_could_throw_p (gimple_op (call, i))) |
342 { | 481 { |
343 if (possibly_throws && flag_non_call_exceptions) | 482 if (possibly_throws && cfun->can_throw_non_call_exceptions) |
344 { | 483 { |
345 if (dump_file) | 484 if (dump_file) |
346 fprintf (dump_file, " operand can throw; looping\n"); | 485 fprintf (dump_file, " operand can throw; looping\n"); |
347 local->looping = true; | 486 local->looping = true; |
348 } | 487 } |
365 outside the compilation unit or an indirect call we punt. This | 504 outside the compilation unit or an indirect call we punt. This |
366 leaves local calls which will be processed by following the call | 505 leaves local calls which will be processed by following the call |
367 graph. */ | 506 graph. */ |
368 if (callee_t) | 507 if (callee_t) |
369 { | 508 { |
509 enum pure_const_state_e call_state; | |
510 bool call_looping; | |
511 | |
512 if (special_builtin_state (&call_state, &call_looping, callee_t)) | |
513 { | |
514 worse_state (&local->pure_const_state, &local->looping, | |
515 call_state, call_looping); | |
516 return; | |
517 } | |
370 /* When bad things happen to bad functions, they cannot be const | 518 /* When bad things happen to bad functions, they cannot be const |
371 or pure. */ | 519 or pure. */ |
372 if (setjmp_call_p (callee_t)) | 520 if (setjmp_call_p (callee_t)) |
373 { | 521 { |
374 if (dump_file) | 522 if (dump_file) |
397 { | 545 { |
398 if (dump_file) | 546 if (dump_file) |
399 fprintf (dump_file, " Recursive call can loop.\n"); | 547 fprintf (dump_file, " Recursive call can loop.\n"); |
400 local->looping = true; | 548 local->looping = true; |
401 } | 549 } |
402 /* Either calle is unknown or we are doing local analysis. | 550 /* Either callee is unknown or we are doing local analysis. |
403 Look to see if there are any bits available for the callee (such as by | 551 Look to see if there are any bits available for the callee (such as by |
404 declaration or because it is builtin) and process solely on the basis of | 552 declaration or because it is builtin) and process solely on the basis of |
405 those bits. */ | 553 those bits. */ |
406 else if (!ipa || !callee_t) | 554 else if (!ipa) |
407 { | 555 { |
408 if (possibly_throws && flag_non_call_exceptions) | 556 enum pure_const_state_e call_state; |
557 bool call_looping; | |
558 if (possibly_throws && cfun->can_throw_non_call_exceptions) | |
409 { | 559 { |
410 if (dump_file) | 560 if (dump_file) |
411 fprintf (dump_file, " can throw; looping\n"); | 561 fprintf (dump_file, " can throw; looping\n"); |
412 local->looping = true; | 562 local->looping = true; |
413 } | 563 } |
421 fprintf (dump_file, " callee:%s\n", | 571 fprintf (dump_file, " callee:%s\n", |
422 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (callee_t))); | 572 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (callee_t))); |
423 } | 573 } |
424 local->can_throw = true; | 574 local->can_throw = true; |
425 } | 575 } |
426 if (flags & ECF_CONST) | 576 if (dump_file && (dump_flags & TDF_DETAILS)) |
427 { | 577 fprintf (dump_file, " checking flags for call:"); |
428 if (callee_t && DECL_LOOPING_CONST_OR_PURE_P (callee_t)) | 578 state_from_flags (&call_state, &call_looping, flags, |
429 { | 579 ((flags & (ECF_NORETURN | ECF_NOTHROW)) |
430 if (dump_file) | 580 == (ECF_NORETURN | ECF_NOTHROW)) |
431 fprintf (dump_file, " calls looping pure.\n"); | 581 || (!flag_exceptions && (flags & ECF_NORETURN))); |
432 local->looping = true; | 582 worse_state (&local->pure_const_state, &local->looping, |
433 } | 583 call_state, call_looping); |
434 } | |
435 else if (flags & ECF_PURE) | |
436 { | |
437 if (callee_t && DECL_LOOPING_CONST_OR_PURE_P (callee_t)) | |
438 { | |
439 if (dump_file) | |
440 fprintf (dump_file, " calls looping const.\n"); | |
441 local->looping = true; | |
442 } | |
443 if (dump_file) | |
444 fprintf (dump_file, " pure function call in not const\n"); | |
445 if (local->pure_const_state == IPA_CONST) | |
446 local->pure_const_state = IPA_PURE; | |
447 } | |
448 else | |
449 { | |
450 if (dump_file) | |
451 fprintf (dump_file, " uknown function call is not const/pure\n"); | |
452 local->pure_const_state = IPA_NEITHER; | |
453 local->looping = true; | |
454 } | |
455 } | 584 } |
456 /* Direct functions calls are handled by IPA propagation. */ | 585 /* Direct functions calls are handled by IPA propagation. */ |
457 } | 586 } |
458 | 587 |
459 /* Wrapper around check_decl for loads. */ | 588 /* Wrapper around check_decl for loads in local more. */ |
460 | 589 |
461 static bool | 590 static bool |
462 check_load (gimple stmt ATTRIBUTE_UNUSED, tree op, void *data) | 591 check_load (gimple stmt ATTRIBUTE_UNUSED, tree op, void *data) |
463 { | 592 { |
464 if (DECL_P (op)) | 593 if (DECL_P (op)) |
465 check_decl ((funct_state)data, op, false); | 594 check_decl ((funct_state)data, op, false, false); |
466 else | 595 else |
467 check_op ((funct_state)data, op, false); | 596 check_op ((funct_state)data, op, false); |
468 return false; | 597 return false; |
469 } | 598 } |
470 | 599 |
471 /* Wrapper around check_decl for stores. */ | 600 /* Wrapper around check_decl for stores in local more. */ |
472 | 601 |
473 static bool | 602 static bool |
474 check_store (gimple stmt ATTRIBUTE_UNUSED, tree op, void *data) | 603 check_store (gimple stmt ATTRIBUTE_UNUSED, tree op, void *data) |
475 { | 604 { |
476 if (DECL_P (op)) | 605 if (DECL_P (op)) |
477 check_decl ((funct_state)data, op, true); | 606 check_decl ((funct_state)data, op, true, false); |
607 else | |
608 check_op ((funct_state)data, op, true); | |
609 return false; | |
610 } | |
611 | |
612 /* Wrapper around check_decl for loads in ipa mode. */ | |
613 | |
614 static bool | |
615 check_ipa_load (gimple stmt ATTRIBUTE_UNUSED, tree op, void *data) | |
616 { | |
617 if (DECL_P (op)) | |
618 check_decl ((funct_state)data, op, false, true); | |
619 else | |
620 check_op ((funct_state)data, op, false); | |
621 return false; | |
622 } | |
623 | |
624 /* Wrapper around check_decl for stores in ipa mode. */ | |
625 | |
626 static bool | |
627 check_ipa_store (gimple stmt ATTRIBUTE_UNUSED, tree op, void *data) | |
628 { | |
629 if (DECL_P (op)) | |
630 check_decl ((funct_state)data, op, true, true); | |
478 else | 631 else |
479 check_op ((funct_state)data, op, true); | 632 check_op ((funct_state)data, op, true); |
480 return false; | 633 return false; |
481 } | 634 } |
482 | 635 |
495 { | 648 { |
496 fprintf (dump_file, " scanning: "); | 649 fprintf (dump_file, " scanning: "); |
497 print_gimple_stmt (dump_file, stmt, 0, 0); | 650 print_gimple_stmt (dump_file, stmt, 0, 0); |
498 } | 651 } |
499 | 652 |
653 if (gimple_has_volatile_ops (stmt)) | |
654 { | |
655 local->pure_const_state = IPA_NEITHER; | |
656 if (dump_file) | |
657 fprintf (dump_file, " Volatile stmt is not const/pure\n"); | |
658 } | |
659 | |
500 /* Look for loads and stores. */ | 660 /* Look for loads and stores. */ |
501 walk_stmt_load_store_ops (stmt, local, check_load, check_store); | 661 walk_stmt_load_store_ops (stmt, local, |
662 ipa ? check_ipa_load : check_load, | |
663 ipa ? check_ipa_store : check_store); | |
502 | 664 |
503 if (gimple_code (stmt) != GIMPLE_CALL | 665 if (gimple_code (stmt) != GIMPLE_CALL |
504 && stmt_could_throw_p (stmt)) | 666 && stmt_could_throw_p (stmt)) |
505 { | 667 { |
506 if (flag_non_call_exceptions) | 668 if (cfun->can_throw_non_call_exceptions) |
507 { | 669 { |
508 if (dump_file) | 670 if (dump_file) |
509 fprintf (dump_file, " can throw; looping"); | 671 fprintf (dump_file, " can throw; looping"); |
510 local->looping = true; | 672 local->looping = true; |
511 } | 673 } |
607 indication of possible infinite loop side | 769 indication of possible infinite loop side |
608 effect. */ | 770 effect. */ |
609 if (mark_dfs_back_edges ()) | 771 if (mark_dfs_back_edges ()) |
610 { | 772 { |
611 /* Preheaders are needed for SCEV to work. | 773 /* Preheaders are needed for SCEV to work. |
612 Simple lateches and recorded exits improve chances that loop will | 774 Simple latches and recorded exits improve chances that loop will |
613 proved to be finite in testcases such as in loop-15.c and loop-24.c */ | 775 proved to be finite in testcases such as in loop-15.c and loop-24.c */ |
614 loop_optimizer_init (LOOPS_NORMAL | 776 loop_optimizer_init (LOOPS_NORMAL |
615 | LOOPS_HAVE_RECORDED_EXITS); | 777 | LOOPS_HAVE_RECORDED_EXITS); |
616 if (dump_file && (dump_flags & TDF_DETAILS)) | 778 if (dump_file && (dump_flags & TDF_DETAILS)) |
617 flow_loops_dump (dump_file, NULL, 0); | 779 flow_loops_dump (dump_file, NULL, 0); |
638 } | 800 } |
639 loop_optimizer_finalize (); | 801 loop_optimizer_finalize (); |
640 } | 802 } |
641 } | 803 } |
642 | 804 |
643 if (TREE_READONLY (decl)) | 805 if (dump_file && (dump_flags & TDF_DETAILS)) |
644 { | 806 fprintf (dump_file, " checking previously known:"); |
645 l->pure_const_state = IPA_CONST; | 807 state_from_flags (&l->state_previously_known, &l->looping_previously_known, |
646 l->state_previously_known = IPA_CONST; | 808 flags_from_decl_or_type (fn->decl), |
647 if (!DECL_LOOPING_CONST_OR_PURE_P (decl)) | 809 cgraph_node_cannot_return (fn)); |
648 l->looping = false, l->looping_previously_known = false; | 810 |
649 } | 811 better_state (&l->pure_const_state, &l->looping, |
650 if (DECL_PURE_P (decl)) | 812 l->state_previously_known, |
651 { | 813 l->looping_previously_known); |
652 if (l->pure_const_state != IPA_CONST) | |
653 l->pure_const_state = IPA_PURE; | |
654 l->state_previously_known = IPA_PURE; | |
655 if (!DECL_LOOPING_CONST_OR_PURE_P (decl)) | |
656 l->looping = false, l->looping_previously_known = false; | |
657 } | |
658 if (TREE_NOTHROW (decl)) | 814 if (TREE_NOTHROW (decl)) |
659 l->can_throw = false; | 815 l->can_throw = false; |
660 | 816 |
661 pop_cfun (); | 817 pop_cfun (); |
662 current_function_decl = old_decl; | 818 current_function_decl = old_decl; |
695 | 851 |
696 static void | 852 static void |
697 duplicate_node_data (struct cgraph_node *src, struct cgraph_node *dst, | 853 duplicate_node_data (struct cgraph_node *src, struct cgraph_node *dst, |
698 void *data ATTRIBUTE_UNUSED) | 854 void *data ATTRIBUTE_UNUSED) |
699 { | 855 { |
700 if (get_function_state (src)) | 856 if (has_function_state (src)) |
701 { | 857 { |
702 funct_state l = XNEW (struct funct_state_d); | 858 funct_state l = XNEW (struct funct_state_d); |
703 gcc_assert (!get_function_state (dst)); | 859 gcc_assert (!has_function_state (dst)); |
704 memcpy (l, get_function_state (src), sizeof (*l)); | 860 memcpy (l, get_function_state (src), sizeof (*l)); |
705 set_function_state (dst, l); | 861 set_function_state (dst, l); |
706 } | 862 } |
707 } | 863 } |
708 | 864 |
709 /* Called when new clone is inserted to callgraph late. */ | 865 /* Called when new clone is inserted to callgraph late. */ |
710 | 866 |
711 static void | 867 static void |
712 remove_node_data (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED) | 868 remove_node_data (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED) |
713 { | 869 { |
714 if (get_function_state (node)) | 870 if (has_function_state (node)) |
715 { | 871 { |
716 free (get_function_state (node)); | 872 funct_state l = get_function_state (node); |
873 if (l != &varying_state) | |
874 free (l); | |
717 set_function_state (node, NULL); | 875 set_function_state (node, NULL); |
718 } | 876 } |
719 } | 877 } |
720 | 878 |
721 | 879 |
756 | 914 |
757 /* Process all of the functions. | 915 /* Process all of the functions. |
758 | 916 |
759 We process AVAIL_OVERWRITABLE functions. We can not use the results | 917 We process AVAIL_OVERWRITABLE functions. We can not use the results |
760 by default, but the info can be used at LTO with -fwhole-program or | 918 by default, but the info can be used at LTO with -fwhole-program or |
761 when function got clonned and the clone is AVAILABLE. */ | 919 when function got cloned and the clone is AVAILABLE. */ |
762 | 920 |
763 for (node = cgraph_nodes; node; node = node->next) | 921 for (node = cgraph_nodes; node; node = node->next) |
764 if (cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE) | 922 if (cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE) |
765 set_function_state (node, analyze_function (node, true)); | 923 set_function_state (node, analyze_function (node, true)); |
766 | 924 |
782 cgraph_node_set_iterator csi; | 940 cgraph_node_set_iterator csi; |
783 | 941 |
784 for (csi = csi_start (set); !csi_end_p (csi); csi_next (&csi)) | 942 for (csi = csi_start (set); !csi_end_p (csi); csi_next (&csi)) |
785 { | 943 { |
786 node = csi_node (csi); | 944 node = csi_node (csi); |
787 if (node->analyzed && get_function_state (node) != NULL) | 945 if (node->analyzed && has_function_state (node)) |
788 count++; | 946 count++; |
789 } | 947 } |
790 | 948 |
791 lto_output_uleb128_stream (ob->main_stream, count); | 949 lto_output_uleb128_stream (ob->main_stream, count); |
792 | 950 |
793 /* Process all of the functions. */ | 951 /* Process all of the functions. */ |
794 for (csi = csi_start (set); !csi_end_p (csi); csi_next (&csi)) | 952 for (csi = csi_start (set); !csi_end_p (csi); csi_next (&csi)) |
795 { | 953 { |
796 node = csi_node (csi); | 954 node = csi_node (csi); |
797 if (node->analyzed && get_function_state (node) != NULL) | 955 if (node->analyzed && has_function_state (node)) |
798 { | 956 { |
799 struct bitpack_d *bp; | 957 struct bitpack_d bp; |
800 funct_state fs; | 958 funct_state fs; |
801 int node_ref; | 959 int node_ref; |
802 lto_cgraph_encoder_t encoder; | 960 lto_cgraph_encoder_t encoder; |
803 | 961 |
804 fs = get_function_state (node); | 962 fs = get_function_state (node); |
807 node_ref = lto_cgraph_encoder_encode (encoder, node); | 965 node_ref = lto_cgraph_encoder_encode (encoder, node); |
808 lto_output_uleb128_stream (ob->main_stream, node_ref); | 966 lto_output_uleb128_stream (ob->main_stream, node_ref); |
809 | 967 |
810 /* Note that flags will need to be read in the opposite | 968 /* Note that flags will need to be read in the opposite |
811 order as we are pushing the bitflags into FLAGS. */ | 969 order as we are pushing the bitflags into FLAGS. */ |
812 bp = bitpack_create (); | 970 bp = bitpack_create (ob->main_stream); |
813 bp_pack_value (bp, fs->pure_const_state, 2); | 971 bp_pack_value (&bp, fs->pure_const_state, 2); |
814 bp_pack_value (bp, fs->state_previously_known, 2); | 972 bp_pack_value (&bp, fs->state_previously_known, 2); |
815 bp_pack_value (bp, fs->looping_previously_known, 1); | 973 bp_pack_value (&bp, fs->looping_previously_known, 1); |
816 bp_pack_value (bp, fs->looping, 1); | 974 bp_pack_value (&bp, fs->looping, 1); |
817 bp_pack_value (bp, fs->can_throw, 1); | 975 bp_pack_value (&bp, fs->can_throw, 1); |
818 lto_output_bitpack (ob->main_stream, bp); | 976 lto_output_bitpack (&bp); |
819 bitpack_delete (bp); | |
820 } | 977 } |
821 } | 978 } |
822 | 979 |
823 lto_destroy_simple_output_block (ob); | 980 lto_destroy_simple_output_block (ob); |
824 } | 981 } |
849 | 1006 |
850 for (i = 0; i < count; i++) | 1007 for (i = 0; i < count; i++) |
851 { | 1008 { |
852 unsigned int index; | 1009 unsigned int index; |
853 struct cgraph_node *node; | 1010 struct cgraph_node *node; |
854 struct bitpack_d *bp; | 1011 struct bitpack_d bp; |
855 funct_state fs; | 1012 funct_state fs; |
856 lto_cgraph_encoder_t encoder; | 1013 lto_cgraph_encoder_t encoder; |
857 | 1014 |
858 fs = XCNEW (struct funct_state_d); | 1015 fs = XCNEW (struct funct_state_d); |
859 index = lto_input_uleb128 (ib); | 1016 index = lto_input_uleb128 (ib); |
864 /* Note that the flags must be read in the opposite | 1021 /* Note that the flags must be read in the opposite |
865 order in which they were written (the bitflags were | 1022 order in which they were written (the bitflags were |
866 pushed into FLAGS). */ | 1023 pushed into FLAGS). */ |
867 bp = lto_input_bitpack (ib); | 1024 bp = lto_input_bitpack (ib); |
868 fs->pure_const_state | 1025 fs->pure_const_state |
869 = (enum pure_const_state_e) bp_unpack_value (bp, 2); | 1026 = (enum pure_const_state_e) bp_unpack_value (&bp, 2); |
870 fs->state_previously_known | 1027 fs->state_previously_known |
871 = (enum pure_const_state_e) bp_unpack_value (bp, 2); | 1028 = (enum pure_const_state_e) bp_unpack_value (&bp, 2); |
872 fs->looping_previously_known = bp_unpack_value (bp, 1); | 1029 fs->looping_previously_known = bp_unpack_value (&bp, 1); |
873 fs->looping = bp_unpack_value (bp, 1); | 1030 fs->looping = bp_unpack_value (&bp, 1); |
874 fs->can_throw = bp_unpack_value (bp, 1); | 1031 fs->can_throw = bp_unpack_value (&bp, 1); |
875 bitpack_delete (bp); | 1032 if (dump_file) |
1033 { | |
1034 int flags = flags_from_decl_or_type (node->decl); | |
1035 fprintf (dump_file, "Read info for %s/%i ", | |
1036 cgraph_node_name (node), | |
1037 node->uid); | |
1038 if (flags & ECF_CONST) | |
1039 fprintf (dump_file, " const"); | |
1040 if (flags & ECF_PURE) | |
1041 fprintf (dump_file, " pure"); | |
1042 if (flags & ECF_NOTHROW) | |
1043 fprintf (dump_file, " nothrow"); | |
1044 fprintf (dump_file, "\n pure const state: %s\n", | |
1045 pure_const_names[fs->pure_const_state]); | |
1046 fprintf (dump_file, " previously known state: %s\n", | |
1047 pure_const_names[fs->looping_previously_known]); | |
1048 if (fs->looping) | |
1049 fprintf (dump_file," function is locally looping\n"); | |
1050 if (fs->looping_previously_known) | |
1051 fprintf (dump_file," function is previously known looping\n"); | |
1052 if (fs->can_throw) | |
1053 fprintf (dump_file," function is locally throwing\n"); | |
1054 } | |
876 } | 1055 } |
877 | 1056 |
878 lto_destroy_simple_input_block (file_data, | 1057 lto_destroy_simple_input_block (file_data, |
879 LTO_section_ipa_pure_const, | 1058 LTO_section_ipa_pure_const, |
880 ib, data, len); | 1059 ib, data, len); |
899 if (e->callee == node) | 1078 if (e->callee == node) |
900 return true; | 1079 return true; |
901 return false; | 1080 return false; |
902 } | 1081 } |
903 | 1082 |
904 /* Produce the global information by preforming a transitive closure | 1083 /* Produce transitive closure over the callgraph and compute pure/const |
905 on the local information that was produced by generate_summary. | 1084 attributes. */ |
906 Note that there is no function_transform pass since this only | 1085 |
907 updates the function_decl. */ | 1086 static void |
908 | 1087 propagate_pure_const (void) |
909 static unsigned int | |
910 propagate (void) | |
911 { | 1088 { |
912 struct cgraph_node *node; | 1089 struct cgraph_node *node; |
913 struct cgraph_node *w; | 1090 struct cgraph_node *w; |
914 struct cgraph_node **order = | 1091 struct cgraph_node **order = |
915 XCNEWVEC (struct cgraph_node *, cgraph_n_nodes); | 1092 XCNEWVEC (struct cgraph_node *, cgraph_n_nodes); |
916 int order_pos; | 1093 int order_pos; |
917 int i; | 1094 int i; |
918 struct ipa_dfs_info * w_info; | 1095 struct ipa_dfs_info * w_info; |
919 | 1096 |
920 cgraph_remove_function_insertion_hook (function_insertion_hook_holder); | |
921 cgraph_remove_node_duplication_hook (node_duplication_hook_holder); | |
922 cgraph_remove_node_removal_hook (node_removal_hook_holder); | |
923 order_pos = ipa_utils_reduced_inorder (order, true, false, NULL); | 1097 order_pos = ipa_utils_reduced_inorder (order, true, false, NULL); |
924 if (dump_file) | 1098 if (dump_file) |
925 { | 1099 { |
926 dump_cgraph (dump_file); | 1100 dump_cgraph (dump_file); |
927 ipa_utils_print_order(dump_file, "reduced", order, order_pos); | 1101 ipa_utils_print_order(dump_file, "reduced", order, order_pos); |
936 enum pure_const_state_e pure_const_state = IPA_CONST; | 1110 enum pure_const_state_e pure_const_state = IPA_CONST; |
937 bool looping = false; | 1111 bool looping = false; |
938 int count = 0; | 1112 int count = 0; |
939 node = order[i]; | 1113 node = order[i]; |
940 | 1114 |
1115 if (dump_file && (dump_flags & TDF_DETAILS)) | |
1116 fprintf (dump_file, "Starting cycle\n"); | |
1117 | |
941 /* Find the worst state for any node in the cycle. */ | 1118 /* Find the worst state for any node in the cycle. */ |
942 w = node; | 1119 w = node; |
943 while (w) | 1120 while (w && pure_const_state != IPA_NEITHER) |
944 { | 1121 { |
945 struct cgraph_edge *e; | 1122 struct cgraph_edge *e; |
1123 struct cgraph_edge *ie; | |
1124 int i; | |
1125 struct ipa_ref *ref; | |
1126 | |
946 funct_state w_l = get_function_state (w); | 1127 funct_state w_l = get_function_state (w); |
947 if (pure_const_state < w_l->pure_const_state) | 1128 if (dump_file && (dump_flags & TDF_DETAILS)) |
948 pure_const_state = w_l->pure_const_state; | 1129 fprintf (dump_file, " Visiting %s/%i state:%s looping %i\n", |
949 | 1130 cgraph_node_name (w), |
950 if (w_l->looping) | 1131 w->uid, |
951 looping = true; | 1132 pure_const_names[w_l->pure_const_state], |
1133 w_l->looping); | |
1134 | |
1135 /* First merge in function body properties. */ | |
1136 worse_state (&pure_const_state, &looping, | |
1137 w_l->pure_const_state, w_l->looping); | |
1138 if (pure_const_state == IPA_NEITHER) | |
1139 break; | |
1140 | |
1141 /* For overwritable nodes we can not assume anything. */ | |
952 if (cgraph_function_body_availability (w) == AVAIL_OVERWRITABLE) | 1142 if (cgraph_function_body_availability (w) == AVAIL_OVERWRITABLE) |
953 { | 1143 { |
954 looping |= w_l->looping_previously_known; | 1144 worse_state (&pure_const_state, &looping, |
955 if (pure_const_state < w_l->state_previously_known) | 1145 w_l->state_previously_known, |
956 pure_const_state = w_l->state_previously_known; | 1146 w_l->looping_previously_known); |
1147 if (dump_file && (dump_flags & TDF_DETAILS)) | |
1148 { | |
1149 fprintf (dump_file, | |
1150 " Overwritable. state %s looping %i\n", | |
1151 pure_const_names[w_l->state_previously_known], | |
1152 w_l->looping_previously_known); | |
1153 } | |
1154 break; | |
957 } | 1155 } |
958 | 1156 |
959 if (pure_const_state == IPA_NEITHER) | |
960 break; | |
961 | |
962 count++; | 1157 count++; |
963 | 1158 |
1159 /* We consider recursive cycles as possibly infinite. | |
1160 This might be relaxed since infinite recursion leads to stack | |
1161 overflow. */ | |
964 if (count > 1) | 1162 if (count > 1) |
965 looping = true; | 1163 looping = true; |
966 | 1164 |
1165 /* Now walk the edges and merge in callee properties. */ | |
967 for (e = w->callees; e; e = e->next_callee) | 1166 for (e = w->callees; e; e = e->next_callee) |
968 { | 1167 { |
969 struct cgraph_node *y = e->callee; | 1168 struct cgraph_node *y = e->callee; |
970 | 1169 enum pure_const_state_e edge_state = IPA_CONST; |
1170 bool edge_looping = false; | |
1171 | |
1172 if (dump_file && (dump_flags & TDF_DETAILS)) | |
1173 { | |
1174 fprintf (dump_file, | |
1175 " Call to %s/%i", | |
1176 cgraph_node_name (e->callee), | |
1177 e->callee->uid); | |
1178 } | |
971 if (cgraph_function_body_availability (y) > AVAIL_OVERWRITABLE) | 1179 if (cgraph_function_body_availability (y) > AVAIL_OVERWRITABLE) |
972 { | 1180 { |
973 funct_state y_l = get_function_state (y); | 1181 funct_state y_l = get_function_state (y); |
974 if (pure_const_state < y_l->pure_const_state) | 1182 if (dump_file && (dump_flags & TDF_DETAILS)) |
975 pure_const_state = y_l->pure_const_state; | 1183 { |
976 if (pure_const_state == IPA_NEITHER) | 1184 fprintf (dump_file, |
1185 " state:%s looping:%i\n", | |
1186 pure_const_names[y_l->pure_const_state], | |
1187 y_l->looping); | |
1188 } | |
1189 if (y_l->pure_const_state > IPA_PURE | |
1190 && cgraph_edge_cannot_lead_to_return (e)) | |
1191 { | |
1192 if (dump_file && (dump_flags & TDF_DETAILS)) | |
1193 fprintf (dump_file, | |
1194 " Ignoring side effects" | |
1195 " -> pure, looping\n"); | |
1196 edge_state = IPA_PURE; | |
1197 edge_looping = true; | |
1198 } | |
1199 else | |
1200 { | |
1201 edge_state = y_l->pure_const_state; | |
1202 edge_looping = y_l->looping; | |
1203 } | |
1204 } | |
1205 else if (special_builtin_state (&edge_state, &edge_looping, | |
1206 y->decl)) | |
1207 ; | |
1208 else | |
1209 state_from_flags (&edge_state, &edge_looping, | |
1210 flags_from_decl_or_type (y->decl), | |
1211 cgraph_edge_cannot_lead_to_return (e)); | |
1212 | |
1213 /* Merge the results with what we already know. */ | |
1214 better_state (&edge_state, &edge_looping, | |
1215 w_l->state_previously_known, | |
1216 w_l->looping_previously_known); | |
1217 worse_state (&pure_const_state, &looping, | |
1218 edge_state, edge_looping); | |
1219 if (pure_const_state == IPA_NEITHER) | |
1220 break; | |
1221 } | |
1222 if (pure_const_state == IPA_NEITHER) | |
1223 break; | |
1224 | |
1225 /* Now process the indirect call. */ | |
1226 for (ie = node->indirect_calls; ie; ie = ie->next_callee) | |
1227 { | |
1228 enum pure_const_state_e edge_state = IPA_CONST; | |
1229 bool edge_looping = false; | |
1230 | |
1231 if (dump_file && (dump_flags & TDF_DETAILS)) | |
1232 fprintf (dump_file, " Indirect call"); | |
1233 state_from_flags (&edge_state, &edge_looping, | |
1234 ie->indirect_info->ecf_flags, | |
1235 cgraph_edge_cannot_lead_to_return (ie)); | |
1236 /* Merge the results with what we already know. */ | |
1237 better_state (&edge_state, &edge_looping, | |
1238 w_l->state_previously_known, | |
1239 w_l->looping_previously_known); | |
1240 worse_state (&pure_const_state, &looping, | |
1241 edge_state, edge_looping); | |
1242 if (pure_const_state == IPA_NEITHER) | |
1243 break; | |
1244 } | |
1245 if (pure_const_state == IPA_NEITHER) | |
1246 break; | |
1247 | |
1248 /* And finally all loads and stores. */ | |
1249 for (i = 0; ipa_ref_list_reference_iterate (&node->ref_list, i, ref); i++) | |
1250 { | |
1251 enum pure_const_state_e ref_state = IPA_CONST; | |
1252 bool ref_looping = false; | |
1253 switch (ref->use) | |
1254 { | |
1255 case IPA_REF_LOAD: | |
1256 /* readonly reads are safe. */ | |
1257 if (TREE_READONLY (ipa_ref_varpool_node (ref)->decl)) | |
977 break; | 1258 break; |
978 if (y_l->looping) | 1259 if (dump_file && (dump_flags & TDF_DETAILS)) |
979 looping = true; | 1260 fprintf (dump_file, " nonreadonly global var read\n"); |
1261 ref_state = IPA_PURE; | |
1262 break; | |
1263 case IPA_REF_STORE: | |
1264 if (ipa_ref_cannot_lead_to_return (ref)) | |
1265 break; | |
1266 ref_state = IPA_NEITHER; | |
1267 if (dump_file && (dump_flags & TDF_DETAILS)) | |
1268 fprintf (dump_file, " global var write\n"); | |
1269 break; | |
1270 case IPA_REF_ADDR: | |
1271 break; | |
980 } | 1272 } |
981 else | 1273 better_state (&ref_state, &ref_looping, |
982 { | 1274 w_l->state_previously_known, |
983 int flags = flags_from_decl_or_type (y->decl); | 1275 w_l->looping_previously_known); |
984 | 1276 worse_state (&pure_const_state, &looping, |
985 if (flags & ECF_LOOPING_CONST_OR_PURE) | 1277 ref_state, ref_looping); |
986 looping = true; | 1278 if (pure_const_state == IPA_NEITHER) |
987 if (flags & ECF_CONST) | 1279 break; |
988 ; | |
989 else if ((flags & ECF_PURE) && pure_const_state == IPA_CONST) | |
990 pure_const_state = IPA_PURE; | |
991 else | |
992 pure_const_state = IPA_NEITHER, looping = true; | |
993 | |
994 } | |
995 } | 1280 } |
996 w_info = (struct ipa_dfs_info *) w->aux; | 1281 w_info = (struct ipa_dfs_info *) w->aux; |
997 w = w_info->next_cycle; | 1282 w = w_info->next_cycle; |
998 } | 1283 } |
1284 if (dump_file && (dump_flags & TDF_DETAILS)) | |
1285 fprintf (dump_file, "Result %s looping %i\n", | |
1286 pure_const_names [pure_const_state], | |
1287 looping); | |
999 | 1288 |
1000 /* Copy back the region's pure_const_state which is shared by | 1289 /* Copy back the region's pure_const_state which is shared by |
1001 all nodes in the region. */ | 1290 all nodes in the region. */ |
1002 w = node; | 1291 w = node; |
1003 while (w) | 1292 while (w) |
1006 enum pure_const_state_e this_state = pure_const_state; | 1295 enum pure_const_state_e this_state = pure_const_state; |
1007 bool this_looping = looping; | 1296 bool this_looping = looping; |
1008 | 1297 |
1009 if (w_l->state_previously_known != IPA_NEITHER | 1298 if (w_l->state_previously_known != IPA_NEITHER |
1010 && this_state > w_l->state_previously_known) | 1299 && this_state > w_l->state_previously_known) |
1011 this_state = w_l->state_previously_known; | 1300 { |
1301 this_state = w_l->state_previously_known; | |
1302 this_looping |= w_l->looping_previously_known; | |
1303 } | |
1012 if (!this_looping && self_recursive_p (w)) | 1304 if (!this_looping && self_recursive_p (w)) |
1013 this_looping = true; | 1305 this_looping = true; |
1014 if (!w_l->looping_previously_known) | 1306 if (!w_l->looping_previously_known) |
1015 this_looping = false; | 1307 this_looping = false; |
1016 | 1308 |
1027 if (dump_file) | 1319 if (dump_file) |
1028 fprintf (dump_file, "Function found to be %sconst: %s\n", | 1320 fprintf (dump_file, "Function found to be %sconst: %s\n", |
1029 this_looping ? "looping " : "", | 1321 this_looping ? "looping " : "", |
1030 cgraph_node_name (w)); | 1322 cgraph_node_name (w)); |
1031 } | 1323 } |
1032 cgraph_set_readonly_flag (w, true); | 1324 cgraph_set_const_flag (w, true, this_looping); |
1033 cgraph_set_looping_const_or_pure_flag (w, this_looping); | |
1034 break; | 1325 break; |
1035 | 1326 |
1036 case IPA_PURE: | 1327 case IPA_PURE: |
1037 if (!DECL_PURE_P (w->decl)) | 1328 if (!DECL_PURE_P (w->decl)) |
1038 { | 1329 { |
1040 if (dump_file) | 1331 if (dump_file) |
1041 fprintf (dump_file, "Function found to be %spure: %s\n", | 1332 fprintf (dump_file, "Function found to be %spure: %s\n", |
1042 this_looping ? "looping " : "", | 1333 this_looping ? "looping " : "", |
1043 cgraph_node_name (w)); | 1334 cgraph_node_name (w)); |
1044 } | 1335 } |
1045 cgraph_set_pure_flag (w, true); | 1336 cgraph_set_pure_flag (w, true, this_looping); |
1046 cgraph_set_looping_const_or_pure_flag (w, this_looping); | |
1047 break; | 1337 break; |
1048 | 1338 |
1049 default: | 1339 default: |
1050 break; | 1340 break; |
1051 } | 1341 } |
1063 w_info = (struct ipa_dfs_info *) node->aux; | 1353 w_info = (struct ipa_dfs_info *) node->aux; |
1064 free (node->aux); | 1354 free (node->aux); |
1065 node->aux = NULL; | 1355 node->aux = NULL; |
1066 } | 1356 } |
1067 } | 1357 } |
1358 | |
1359 free (order); | |
1360 } | |
1361 | |
1362 /* Produce transitive closure over the callgraph and compute nothrow | |
1363 attributes. */ | |
1364 | |
1365 static void | |
1366 propagate_nothrow (void) | |
1367 { | |
1368 struct cgraph_node *node; | |
1369 struct cgraph_node *w; | |
1370 struct cgraph_node **order = | |
1371 XCNEWVEC (struct cgraph_node *, cgraph_n_nodes); | |
1372 int order_pos; | |
1373 int i; | |
1374 struct ipa_dfs_info * w_info; | |
1375 | |
1068 order_pos = ipa_utils_reduced_inorder (order, true, false, ignore_edge); | 1376 order_pos = ipa_utils_reduced_inorder (order, true, false, ignore_edge); |
1069 if (dump_file) | 1377 if (dump_file) |
1070 { | 1378 { |
1071 dump_cgraph (dump_file); | 1379 dump_cgraph (dump_file); |
1072 ipa_utils_print_order(dump_file, "reduced for nothrow", order, order_pos); | 1380 ipa_utils_print_order(dump_file, "reduced for nothrow", order, order_pos); |
1073 } | 1381 } |
1382 | |
1074 /* Propagate the local information thru the call graph to produce | 1383 /* Propagate the local information thru the call graph to produce |
1075 the global information. All the nodes within a cycle will have | 1384 the global information. All the nodes within a cycle will have |
1076 the same info so we collapse cycles first. Then we can do the | 1385 the same info so we collapse cycles first. Then we can do the |
1077 propagation in one pass from the leaves to the roots. */ | 1386 propagation in one pass from the leaves to the roots. */ |
1078 for (i = 0; i < order_pos; i++ ) | 1387 for (i = 0; i < order_pos; i++ ) |
1082 | 1391 |
1083 /* Find the worst state for any node in the cycle. */ | 1392 /* Find the worst state for any node in the cycle. */ |
1084 w = node; | 1393 w = node; |
1085 while (w) | 1394 while (w) |
1086 { | 1395 { |
1087 struct cgraph_edge *e; | 1396 struct cgraph_edge *e, *ie; |
1088 funct_state w_l = get_function_state (w); | 1397 funct_state w_l = get_function_state (w); |
1089 | 1398 |
1090 if (w_l->can_throw | 1399 if (w_l->can_throw |
1091 || cgraph_function_body_availability (w) == AVAIL_OVERWRITABLE) | 1400 || cgraph_function_body_availability (w) == AVAIL_OVERWRITABLE) |
1092 can_throw = true; | 1401 can_throw = true; |
1109 can_throw = true; | 1418 can_throw = true; |
1110 } | 1419 } |
1111 else if (e->can_throw_external && !TREE_NOTHROW (y->decl)) | 1420 else if (e->can_throw_external && !TREE_NOTHROW (y->decl)) |
1112 can_throw = true; | 1421 can_throw = true; |
1113 } | 1422 } |
1423 for (ie = node->indirect_calls; ie; ie = ie->next_callee) | |
1424 if (ie->can_throw_external) | |
1425 can_throw = true; | |
1114 w_info = (struct ipa_dfs_info *) w->aux; | 1426 w_info = (struct ipa_dfs_info *) w->aux; |
1115 w = w_info->next_cycle; | 1427 w = w_info->next_cycle; |
1116 } | 1428 } |
1117 | 1429 |
1118 /* Copy back the region's pure_const_state which is shared by | 1430 /* Copy back the region's pure_const_state which is shared by |
1146 { | 1458 { |
1147 w_info = (struct ipa_dfs_info *) node->aux; | 1459 w_info = (struct ipa_dfs_info *) node->aux; |
1148 free (node->aux); | 1460 free (node->aux); |
1149 node->aux = NULL; | 1461 node->aux = NULL; |
1150 } | 1462 } |
1151 if (cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE) | |
1152 free (get_function_state (node)); | |
1153 } | 1463 } |
1154 | 1464 |
1155 free (order); | 1465 free (order); |
1466 } | |
1467 | |
1468 | |
1469 /* Produce the global information by preforming a transitive closure | |
1470 on the local information that was produced by generate_summary. */ | |
1471 | |
1472 static unsigned int | |
1473 propagate (void) | |
1474 { | |
1475 struct cgraph_node *node; | |
1476 | |
1477 cgraph_remove_function_insertion_hook (function_insertion_hook_holder); | |
1478 cgraph_remove_node_duplication_hook (node_duplication_hook_holder); | |
1479 cgraph_remove_node_removal_hook (node_removal_hook_holder); | |
1480 | |
1481 /* Nothrow makes more function to not lead to return and improve | |
1482 later analysis. */ | |
1483 propagate_nothrow (); | |
1484 propagate_pure_const (); | |
1485 | |
1486 /* Cleanup. */ | |
1487 for (node = cgraph_nodes; node; node = node->next) | |
1488 if (has_function_state (node)) | |
1489 free (get_function_state (node)); | |
1156 VEC_free (funct_state, heap, funct_state_vec); | 1490 VEC_free (funct_state, heap, funct_state_vec); |
1157 finish_state (); | 1491 finish_state (); |
1158 return 0; | 1492 return 0; |
1159 } | 1493 } |
1160 | 1494 |
1161 static bool | 1495 static bool |
1162 gate_pure_const (void) | 1496 gate_pure_const (void) |
1163 { | 1497 { |
1164 return (flag_ipa_pure_const | 1498 return (flag_ipa_pure_const |
1165 /* Don't bother doing anything if the program has errors. */ | 1499 /* Don't bother doing anything if the program has errors. */ |
1166 && !(errorcount || sorrycount)); | 1500 && !seen_error ()); |
1167 } | 1501 } |
1168 | 1502 |
1169 struct ipa_opt_pass_d pass_ipa_pure_const = | 1503 struct ipa_opt_pass_d pass_ipa_pure_const = |
1170 { | 1504 { |
1171 { | 1505 { |
1209 return true; | 1543 return true; |
1210 } | 1544 } |
1211 if (cgraph_function_body_availability (node) <= AVAIL_OVERWRITABLE) | 1545 if (cgraph_function_body_availability (node) <= AVAIL_OVERWRITABLE) |
1212 { | 1546 { |
1213 if (dump_file) | 1547 if (dump_file) |
1214 fprintf (dump_file, "Function is not available or overwrittable; not analyzing.\n"); | 1548 fprintf (dump_file, "Function is not available or overwritable; not analyzing.\n"); |
1215 return true; | 1549 return true; |
1216 } | 1550 } |
1217 return false; | 1551 return false; |
1218 } | 1552 } |
1219 | 1553 |
1233 skip = skip_function_for_local_pure_const (node); | 1567 skip = skip_function_for_local_pure_const (node); |
1234 if (!warn_suggest_attribute_const | 1568 if (!warn_suggest_attribute_const |
1235 && !warn_suggest_attribute_pure | 1569 && !warn_suggest_attribute_pure |
1236 && skip) | 1570 && skip) |
1237 return 0; | 1571 return 0; |
1572 | |
1238 l = analyze_function (node, false); | 1573 l = analyze_function (node, false); |
1574 | |
1575 /* Do NORETURN discovery. */ | |
1576 if (!skip && !TREE_THIS_VOLATILE (current_function_decl) | |
1577 && EDGE_COUNT (EXIT_BLOCK_PTR->preds) == 0) | |
1578 { | |
1579 warn_function_noreturn (cfun->decl); | |
1580 if (dump_file) | |
1581 fprintf (dump_file, "Function found to be noreturn: %s\n", | |
1582 lang_hooks.decl_printable_name (current_function_decl, 2)); | |
1583 | |
1584 /* Update declaration and reduce profile to executed once. */ | |
1585 TREE_THIS_VOLATILE (current_function_decl) = 1; | |
1586 if (node->frequency > NODE_FREQUENCY_EXECUTED_ONCE) | |
1587 node->frequency = NODE_FREQUENCY_EXECUTED_ONCE; | |
1588 | |
1589 changed = true; | |
1590 } | |
1239 | 1591 |
1240 switch (l->pure_const_state) | 1592 switch (l->pure_const_state) |
1241 { | 1593 { |
1242 case IPA_CONST: | 1594 case IPA_CONST: |
1243 if (!TREE_READONLY (current_function_decl)) | 1595 if (!TREE_READONLY (current_function_decl)) |
1244 { | 1596 { |
1245 warn_function_const (current_function_decl, !l->looping); | 1597 warn_function_const (current_function_decl, !l->looping); |
1246 if (!skip) | 1598 if (!skip) |
1247 { | 1599 { |
1248 cgraph_set_readonly_flag (node, true); | 1600 cgraph_set_const_flag (node, true, l->looping); |
1249 cgraph_set_looping_const_or_pure_flag (node, l->looping); | |
1250 changed = true; | 1601 changed = true; |
1251 } | 1602 } |
1252 if (dump_file) | 1603 if (dump_file) |
1253 fprintf (dump_file, "Function found to be %sconst: %s\n", | 1604 fprintf (dump_file, "Function found to be %sconst: %s\n", |
1254 l->looping ? "looping " : "", | 1605 l->looping ? "looping " : "", |
1258 else if (DECL_LOOPING_CONST_OR_PURE_P (current_function_decl) | 1609 else if (DECL_LOOPING_CONST_OR_PURE_P (current_function_decl) |
1259 && !l->looping) | 1610 && !l->looping) |
1260 { | 1611 { |
1261 if (!skip) | 1612 if (!skip) |
1262 { | 1613 { |
1263 cgraph_set_looping_const_or_pure_flag (node, false); | 1614 cgraph_set_const_flag (node, true, false); |
1264 changed = true; | 1615 changed = true; |
1265 } | 1616 } |
1266 if (dump_file) | 1617 if (dump_file) |
1267 fprintf (dump_file, "Function found to be non-looping: %s\n", | 1618 fprintf (dump_file, "Function found to be non-looping: %s\n", |
1268 lang_hooks.decl_printable_name (current_function_decl, | 1619 lang_hooks.decl_printable_name (current_function_decl, |
1273 case IPA_PURE: | 1624 case IPA_PURE: |
1274 if (!DECL_PURE_P (current_function_decl)) | 1625 if (!DECL_PURE_P (current_function_decl)) |
1275 { | 1626 { |
1276 if (!skip) | 1627 if (!skip) |
1277 { | 1628 { |
1278 cgraph_set_pure_flag (node, true); | 1629 cgraph_set_pure_flag (node, true, l->looping); |
1279 cgraph_set_looping_const_or_pure_flag (node, l->looping); | |
1280 changed = true; | 1630 changed = true; |
1281 } | 1631 } |
1282 warn_function_pure (current_function_decl, !l->looping); | 1632 warn_function_pure (current_function_decl, !l->looping); |
1283 if (dump_file) | 1633 if (dump_file) |
1284 fprintf (dump_file, "Function found to be %spure: %s\n", | 1634 fprintf (dump_file, "Function found to be %spure: %s\n", |
1289 else if (DECL_LOOPING_CONST_OR_PURE_P (current_function_decl) | 1639 else if (DECL_LOOPING_CONST_OR_PURE_P (current_function_decl) |
1290 && !l->looping) | 1640 && !l->looping) |
1291 { | 1641 { |
1292 if (!skip) | 1642 if (!skip) |
1293 { | 1643 { |
1294 cgraph_set_looping_const_or_pure_flag (node, false); | 1644 cgraph_set_pure_flag (node, true, false); |
1295 changed = true; | 1645 changed = true; |
1296 } | 1646 } |
1297 if (dump_file) | 1647 if (dump_file) |
1298 fprintf (dump_file, "Function found to be non-looping: %s\n", | 1648 fprintf (dump_file, "Function found to be non-looping: %s\n", |
1299 lang_hooks.decl_printable_name (current_function_decl, | 1649 lang_hooks.decl_printable_name (current_function_decl, |