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 (&reg_obstack); 1978 bitmap regs_set = BITMAP_ALLOC (&reg_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 {