Mercurial > hg > CbC > CbC_gcc
comparison gcc/dse.c @ 145:1830386684a0
gcc-9.2.0
author | anatofuz |
---|---|
date | Thu, 13 Feb 2020 11:34:05 +0900 |
parents | 84e7813d76e9 |
children |
comparison
equal
deleted
inserted
replaced
131:84e7813d76e9 | 145:1830386684a0 |
---|---|
1 /* RTL dead store elimination. | 1 /* RTL dead store elimination. |
2 Copyright (C) 2005-2018 Free Software Foundation, Inc. | 2 Copyright (C) 2005-2020 Free Software Foundation, Inc. |
3 | 3 |
4 Contributed by Richard Sandiford <rsandifor@codesourcery.com> | 4 Contributed by Richard Sandiford <rsandifor@codesourcery.com> |
5 and Kenneth Zadeck <zadeck@naturalbridge.com> | 5 and Kenneth Zadeck <zadeck@naturalbridge.com> |
6 | 6 |
7 This file is part of GCC. | 7 This file is part of GCC. |
45 #include "cselib.h" | 45 #include "cselib.h" |
46 #include "tree-pass.h" | 46 #include "tree-pass.h" |
47 #include "explow.h" | 47 #include "explow.h" |
48 #include "expr.h" | 48 #include "expr.h" |
49 #include "dbgcnt.h" | 49 #include "dbgcnt.h" |
50 #include "params.h" | |
51 #include "rtl-iter.h" | 50 #include "rtl-iter.h" |
52 #include "cfgcleanup.h" | 51 #include "cfgcleanup.h" |
52 #include "calls.h" | |
53 | 53 |
54 /* This file contains three techniques for performing Dead Store | 54 /* This file contains three techniques for performing Dead Store |
55 Elimination (dse). | 55 Elimination (dse). |
56 | 56 |
57 * The first technique performs dse locally on any base address. It | 57 * The first technique performs dse locally on any base address. It |
218 static bitmap scratch = NULL; | 218 static bitmap scratch = NULL; |
219 | 219 |
220 struct insn_info_type; | 220 struct insn_info_type; |
221 | 221 |
222 /* This structure holds information about a candidate store. */ | 222 /* This structure holds information about a candidate store. */ |
223 struct store_info | 223 class store_info |
224 { | 224 { |
225 public: | |
225 | 226 |
226 /* False means this is a clobber. */ | 227 /* False means this is a clobber. */ |
227 bool is_set; | 228 bool is_set; |
228 | 229 |
229 /* False if a single HOST_WIDE_INT bitmap is used for positions_needed. */ | 230 /* False if a single HOST_WIDE_INT bitmap is used for positions_needed. */ |
275 int count; | 276 int count; |
276 } large; | 277 } large; |
277 } positions_needed; | 278 } positions_needed; |
278 | 279 |
279 /* The next store info for this insn. */ | 280 /* The next store info for this insn. */ |
280 struct store_info *next; | 281 class store_info *next; |
281 | 282 |
282 /* The right hand side of the store. This is used if there is a | 283 /* The right hand side of the store. This is used if there is a |
283 subsequent reload of the mems address somewhere later in the | 284 subsequent reload of the mems address somewhere later in the |
284 basic block. */ | 285 basic block. */ |
285 rtx rhs; | 286 rtx rhs; |
307 | 308 |
308 static object_allocator<store_info> rtx_store_info_pool ("rtx_store_info_pool"); | 309 static object_allocator<store_info> rtx_store_info_pool ("rtx_store_info_pool"); |
309 | 310 |
310 /* This structure holds information about a load. These are only | 311 /* This structure holds information about a load. These are only |
311 built for rtx bases. */ | 312 built for rtx bases. */ |
312 struct read_info_type | 313 class read_info_type |
313 { | 314 { |
315 public: | |
314 /* The id of the mem group of the base address. */ | 316 /* The id of the mem group of the base address. */ |
315 int group_id; | 317 int group_id; |
316 | 318 |
317 /* The offset of the first byte associated with the operation. */ | 319 /* The offset of the first byte associated with the operation. */ |
318 poly_int64 offset; | 320 poly_int64 offset; |
322 | 324 |
323 /* The mem being read. */ | 325 /* The mem being read. */ |
324 rtx mem; | 326 rtx mem; |
325 | 327 |
326 /* The next read_info for this insn. */ | 328 /* The next read_info for this insn. */ |
327 struct read_info_type *next; | 329 class read_info_type *next; |
328 }; | 330 }; |
329 typedef struct read_info_type *read_info_t; | 331 typedef class read_info_type *read_info_t; |
330 | 332 |
331 static object_allocator<read_info_type> read_info_type_pool ("read_info_pool"); | 333 static object_allocator<read_info_type> read_info_type_pool ("read_info_pool"); |
332 | 334 |
333 /* One of these records is created for each insn. */ | 335 /* One of these records is created for each insn. */ |
334 | 336 |
817 info.fixed_regs_live = insn_info->fixed_regs_live; | 819 info.fixed_regs_live = insn_info->fixed_regs_live; |
818 info.failure = false; | 820 info.failure = false; |
819 for (cur = new_insn; cur; cur = NEXT_INSN (cur)) | 821 for (cur = new_insn; cur; cur = NEXT_INSN (cur)) |
820 { | 822 { |
821 info.current = cur; | 823 info.current = cur; |
822 note_stores (PATTERN (cur), note_add_store, &info); | 824 note_stores (cur, note_add_store, &info); |
823 } | 825 } |
824 | 826 |
825 /* If a failure was flagged above, return 1 so that for_each_inc_dec will | 827 /* If a failure was flagged above, return 1 so that for_each_inc_dec will |
826 return it immediately, communicating the failure to its caller. */ | 828 return it immediately, communicating the failure to its caller. */ |
827 if (info.failure) | 829 if (info.failure) |
1505 mem_addr = plus_constant (get_address_mode (mem), mem_addr, offset); | 1507 mem_addr = plus_constant (get_address_mode (mem), mem_addr, offset); |
1506 | 1508 |
1507 while (ptr) | 1509 while (ptr) |
1508 { | 1510 { |
1509 insn_info_t next = ptr->next_local_store; | 1511 insn_info_t next = ptr->next_local_store; |
1510 struct store_info *s_info = ptr->store_rec; | 1512 class store_info *s_info = ptr->store_rec; |
1511 bool del = true; | 1513 bool del = true; |
1512 | 1514 |
1513 /* Skip the clobbers. We delete the active insn if this insn | 1515 /* Skip the clobbers. We delete the active insn if this insn |
1514 shadows the set. To have been put on the active list, it | 1516 shadows the set. To have been put on the active list, it |
1515 has exactly on set. */ | 1517 has exactly on set. */ |
1839 gap = ((store_info->offset + store_info->width) | 1841 gap = ((store_info->offset + store_info->width) |
1840 - (read_offset + read_width)); | 1842 - (read_offset + read_width)); |
1841 else | 1843 else |
1842 gap = read_offset - store_info->offset; | 1844 gap = read_offset - store_info->offset; |
1843 | 1845 |
1844 if (maybe_ne (gap, 0)) | 1846 if (gap.is_constant () && maybe_ne (gap, 0)) |
1845 { | 1847 { |
1846 poly_int64 shift = gap * BITS_PER_UNIT; | 1848 poly_int64 shift = gap * BITS_PER_UNIT; |
1847 poly_int64 access_size = GET_MODE_SIZE (read_mode) + gap; | 1849 poly_int64 access_size = GET_MODE_SIZE (read_mode) + gap; |
1848 read_reg = find_shift_sequence (access_size, store_info, read_mode, | 1850 read_reg = find_shift_sequence (access_size, store_info, read_mode, |
1849 shift, optimize_bb_for_speed_p (bb), | 1851 shift, optimize_bb_for_speed_p (bb), |
1974 the insns sets the CC and the CC happened to be live at that | 1976 the insns sets the CC and the CC happened to be live at that |
1975 point. This does occasionally happen, see PR 37922. */ | 1977 point. This does occasionally happen, see PR 37922. */ |
1976 bitmap regs_set = BITMAP_ALLOC (®_obstack); | 1978 bitmap regs_set = BITMAP_ALLOC (®_obstack); |
1977 | 1979 |
1978 for (this_insn = insns; this_insn != NULL_RTX; this_insn = NEXT_INSN (this_insn)) | 1980 for (this_insn = insns; this_insn != NULL_RTX; this_insn = NEXT_INSN (this_insn)) |
1979 note_stores (PATTERN (this_insn), look_for_hardregs, regs_set); | 1981 note_stores (this_insn, look_for_hardregs, regs_set); |
1980 | 1982 |
1981 bitmap_and_into (regs_set, regs_live); | 1983 bitmap_and_into (regs_set, regs_live); |
1982 if (!bitmap_empty_p (regs_set)) | 1984 if (!bitmap_empty_p (regs_set)) |
1983 { | 1985 { |
1984 if (dump_file && (dump_flags & TDF_DETAILS)) | 1986 if (dump_file && (dump_flags & TDF_DETAILS)) |
2070 read_info_t read_info; | 2072 read_info_t read_info; |
2071 | 2073 |
2072 insn_info = bb_info->last_insn; | 2074 insn_info = bb_info->last_insn; |
2073 | 2075 |
2074 if ((MEM_ALIAS_SET (mem) == ALIAS_SET_MEMORY_BARRIER) | 2076 if ((MEM_ALIAS_SET (mem) == ALIAS_SET_MEMORY_BARRIER) |
2075 || (MEM_VOLATILE_P (mem))) | 2077 || MEM_VOLATILE_P (mem)) |
2076 { | 2078 { |
2079 if (crtl->stack_protect_guard | |
2080 && (MEM_EXPR (mem) == crtl->stack_protect_guard | |
2081 || (crtl->stack_protect_guard_decl | |
2082 && MEM_EXPR (mem) == crtl->stack_protect_guard_decl)) | |
2083 && MEM_VOLATILE_P (mem)) | |
2084 { | |
2085 /* This is either the stack protector canary on the stack, | |
2086 which ought to be written by a MEM_VOLATILE_P store and | |
2087 thus shouldn't be deleted and is read at the very end of | |
2088 function, but shouldn't conflict with any other store. | |
2089 Or it is __stack_chk_guard variable or TLS or whatever else | |
2090 MEM holding the canary value, which really shouldn't be | |
2091 ever modified in -fstack-protector* protected functions, | |
2092 otherwise the prologue store wouldn't match the epilogue | |
2093 check. */ | |
2094 if (dump_file && (dump_flags & TDF_DETAILS)) | |
2095 fprintf (dump_file, " stack protector canary read ignored.\n"); | |
2096 insn_info->cannot_delete = true; | |
2097 return; | |
2098 } | |
2099 | |
2077 if (dump_file && (dump_flags & TDF_DETAILS)) | 2100 if (dump_file && (dump_flags & TDF_DETAILS)) |
2078 fprintf (dump_file, " adding wild read, volatile or barrier.\n"); | 2101 fprintf (dump_file, " adding wild read, volatile or barrier.\n"); |
2079 add_wild_read (bb_info); | 2102 add_wild_read (bb_info); |
2080 insn_info->cannot_delete = true; | 2103 insn_info->cannot_delete = true; |
2081 return; | 2104 return; |
2318 rtx reg, link, tmp; | 2341 rtx reg, link, tmp; |
2319 | 2342 |
2320 if (!is_int_mode (TYPE_MODE (TREE_VALUE (arg)), &mode)) | 2343 if (!is_int_mode (TYPE_MODE (TREE_VALUE (arg)), &mode)) |
2321 return false; | 2344 return false; |
2322 | 2345 |
2323 reg = targetm.calls.function_arg (args_so_far, mode, NULL_TREE, true); | 2346 function_arg_info arg (mode, /*named=*/true); |
2347 reg = targetm.calls.function_arg (args_so_far, arg); | |
2324 if (!reg || !REG_P (reg) || GET_MODE (reg) != mode) | 2348 if (!reg || !REG_P (reg) || GET_MODE (reg) != mode) |
2325 return false; | 2349 return false; |
2326 | 2350 |
2327 for (link = CALL_INSN_FUNCTION_USAGE (call_insn); | 2351 for (link = CALL_INSN_FUNCTION_USAGE (call_insn); |
2328 link; | 2352 link; |
2350 tmp = gen_int_mode (INTVAL (tmp), mode); | 2374 tmp = gen_int_mode (INTVAL (tmp), mode); |
2351 } | 2375 } |
2352 if (tmp) | 2376 if (tmp) |
2353 args[idx] = tmp; | 2377 args[idx] = tmp; |
2354 | 2378 |
2355 targetm.calls.function_arg_advance (args_so_far, mode, NULL_TREE, true); | 2379 targetm.calls.function_arg_advance (args_so_far, arg); |
2356 } | 2380 } |
2357 if (arg != void_list_node || idx != nargs) | 2381 if (arg != void_list_node || idx != nargs) |
2358 return false; | 2382 return false; |
2359 return true; | 2383 return true; |
2360 } | 2384 } |
2365 copy_fixed_regs (const_bitmap in) | 2389 copy_fixed_regs (const_bitmap in) |
2366 { | 2390 { |
2367 bitmap ret; | 2391 bitmap ret; |
2368 | 2392 |
2369 ret = ALLOC_REG_SET (NULL); | 2393 ret = ALLOC_REG_SET (NULL); |
2370 bitmap_and (ret, in, fixed_reg_set_regset); | 2394 bitmap_and (ret, in, bitmap_view<HARD_REG_SET> (fixed_reg_set)); |
2371 return ret; | 2395 return ret; |
2372 } | 2396 } |
2373 | 2397 |
2374 /* Apply record_store to all candidate stores in INSN. Mark INSN | 2398 /* Apply record_store to all candidate stores in INSN. Mark INSN |
2375 if some part of it is not a candidate store and assigns to a | 2399 if some part of it is not a candidate store and assigns to a |
2376 non-register target. */ | 2400 non-register target. */ |
2377 | 2401 |
2378 static void | 2402 static void |
2379 scan_insn (bb_info_t bb_info, rtx_insn *insn) | 2403 scan_insn (bb_info_t bb_info, rtx_insn *insn, int max_active_local_stores) |
2380 { | 2404 { |
2381 rtx body; | 2405 rtx body; |
2382 insn_info_type *insn_info = insn_info_type_pool.allocate (); | 2406 insn_info_type *insn_info = insn_info_type_pool.allocate (); |
2383 int mems_found = 0; | 2407 int mems_found = 0; |
2384 memset (insn_info, 0, sizeof (struct insn_info_type)); | 2408 memset (insn_info, 0, sizeof (struct insn_info_type)); |
2496 mems_found += record_store (body, bb_info); | 2520 mems_found += record_store (body, bb_info); |
2497 if (dump_file && (dump_flags & TDF_DETAILS)) | 2521 if (dump_file && (dump_flags & TDF_DETAILS)) |
2498 fprintf (dump_file, "handling memset as BLKmode store\n"); | 2522 fprintf (dump_file, "handling memset as BLKmode store\n"); |
2499 if (mems_found == 1) | 2523 if (mems_found == 1) |
2500 { | 2524 { |
2501 if (active_local_stores_len++ | 2525 if (active_local_stores_len++ >= max_active_local_stores) |
2502 >= PARAM_VALUE (PARAM_MAX_DSE_ACTIVE_LOCAL_STORES)) | |
2503 { | 2526 { |
2504 active_local_stores_len = 1; | 2527 active_local_stores_len = 1; |
2505 active_local_stores = NULL; | 2528 active_local_stores = NULL; |
2506 } | 2529 } |
2507 insn_info->fixed_regs_live | 2530 insn_info->fixed_regs_live |
2512 } | 2535 } |
2513 else | 2536 else |
2514 clear_rhs_from_active_local_stores (); | 2537 clear_rhs_from_active_local_stores (); |
2515 } | 2538 } |
2516 } | 2539 } |
2517 else if (SIBLING_CALL_P (insn) && reload_completed) | 2540 else if (SIBLING_CALL_P (insn) |
2541 && (reload_completed || HARD_FRAME_POINTER_IS_ARG_POINTER)) | |
2518 /* Arguments for a sibling call that are pushed to memory are passed | 2542 /* Arguments for a sibling call that are pushed to memory are passed |
2519 using the incoming argument pointer of the current function. After | 2543 using the incoming argument pointer of the current function. After |
2520 reload that might be (and likely is) frame pointer based. */ | 2544 reload that might be (and likely is) frame pointer based. And, if |
2545 it is a frame pointer on the target, even before reload we need to | |
2546 kill frame pointer based stores. */ | |
2521 add_wild_read (bb_info); | 2547 add_wild_read (bb_info); |
2522 else | 2548 else |
2523 /* Every other call, including pure functions, may read any memory | 2549 /* Every other call, including pure functions, may read any memory |
2524 that is not relative to the frame. */ | 2550 that is not relative to the frame. */ |
2525 add_non_frame_wild_read (bb_info); | 2551 add_non_frame_wild_read (bb_info); |
2554 that it can be locally deleted if found dead or used for | 2580 that it can be locally deleted if found dead or used for |
2555 replace_read and redundant constant store elimination. Otherwise mark | 2581 replace_read and redundant constant store elimination. Otherwise mark |
2556 it as cannot delete. This simplifies the processing later. */ | 2582 it as cannot delete. This simplifies the processing later. */ |
2557 if (mems_found == 1) | 2583 if (mems_found == 1) |
2558 { | 2584 { |
2559 if (active_local_stores_len++ | 2585 if (active_local_stores_len++ >= max_active_local_stores) |
2560 >= PARAM_VALUE (PARAM_MAX_DSE_ACTIVE_LOCAL_STORES)) | |
2561 { | 2586 { |
2562 active_local_stores_len = 1; | 2587 active_local_stores_len = 1; |
2563 active_local_stores = NULL; | 2588 active_local_stores = NULL; |
2564 } | 2589 } |
2565 insn_info->fixed_regs_live = copy_fixed_regs (bb_info->regs_live); | 2590 insn_info->fixed_regs_live = copy_fixed_regs (bb_info->regs_live); |
2585 { | 2610 { |
2586 store_info *store_info = insn_info->store_rec; | 2611 store_info *store_info = insn_info->store_rec; |
2587 bool del = false; | 2612 bool del = false; |
2588 | 2613 |
2589 /* If ANY of the store_infos match the cselib group that is | 2614 /* If ANY of the store_infos match the cselib group that is |
2590 being deleted, then the insn can not be deleted. */ | 2615 being deleted, then the insn cannot be deleted. */ |
2591 while (store_info) | 2616 while (store_info) |
2592 { | 2617 { |
2593 if ((store_info->group_id == -1) | 2618 if ((store_info->group_id == -1) |
2594 && (store_info->cse_base == base)) | 2619 && (store_info->cse_base == base)) |
2595 { | 2620 { |
2627 cselib_init (0); | 2652 cselib_init (0); |
2628 all_blocks = BITMAP_ALLOC (NULL); | 2653 all_blocks = BITMAP_ALLOC (NULL); |
2629 bitmap_set_bit (all_blocks, ENTRY_BLOCK); | 2654 bitmap_set_bit (all_blocks, ENTRY_BLOCK); |
2630 bitmap_set_bit (all_blocks, EXIT_BLOCK); | 2655 bitmap_set_bit (all_blocks, EXIT_BLOCK); |
2631 | 2656 |
2657 /* For -O1 reduce the maximum number of active local stores for RTL DSE | |
2658 since this can consume huge amounts of memory (PR89115). */ | |
2659 int max_active_local_stores = param_max_dse_active_local_stores; | |
2660 if (optimize < 2) | |
2661 max_active_local_stores /= 10; | |
2662 | |
2632 FOR_ALL_BB_FN (bb, cfun) | 2663 FOR_ALL_BB_FN (bb, cfun) |
2633 { | 2664 { |
2634 insn_info_t ptr; | 2665 insn_info_t ptr; |
2635 bb_info_t bb_info = dse_bb_info_type_pool.allocate (); | 2666 bb_info_t bb_info = dse_bb_info_type_pool.allocate (); |
2636 | 2667 |
2654 | 2685 |
2655 /* Scan the insns. */ | 2686 /* Scan the insns. */ |
2656 FOR_BB_INSNS (bb, insn) | 2687 FOR_BB_INSNS (bb, insn) |
2657 { | 2688 { |
2658 if (INSN_P (insn)) | 2689 if (INSN_P (insn)) |
2659 scan_insn (bb_info, insn); | 2690 scan_insn (bb_info, insn, max_active_local_stores); |
2660 cselib_process_insn (insn); | 2691 cselib_process_insn (insn); |
2661 if (INSN_P (insn)) | 2692 if (INSN_P (insn)) |
2662 df_simulate_one_insn_forwards (bb, insn, regs_live); | 2693 df_simulate_one_insn_forwards (bb, insn, regs_live); |
2663 } | 2694 } |
2664 | 2695 |
3596 /* DSE can eliminate potentially-trapping MEMs. | 3627 /* DSE can eliminate potentially-trapping MEMs. |
3597 Remove any EH edges associated with them. */ | 3628 Remove any EH edges associated with them. */ |
3598 if ((locally_deleted || globally_deleted) | 3629 if ((locally_deleted || globally_deleted) |
3599 && cfun->can_throw_non_call_exceptions | 3630 && cfun->can_throw_non_call_exceptions |
3600 && purge_all_dead_edges ()) | 3631 && purge_all_dead_edges ()) |
3601 cleanup_cfg (0); | 3632 { |
3633 free_dominance_info (CDI_DOMINATORS); | |
3634 cleanup_cfg (0); | |
3635 } | |
3602 | 3636 |
3603 return 0; | 3637 return 0; |
3604 } | 3638 } |
3605 | 3639 |
3606 namespace { | 3640 namespace { |