From 8d0741923dc99b7876f8faafdc238b59a32d0ffc Mon Sep 17 00:00:00 2001 From: Bernd Schmidt Date: Thu, 29 Jul 2010 12:39:57 +0000 Subject: [PATCH] re PR rtl-optimization/42575 (arm-eabi-gcc 64-bit multiply weirdness) PR rtl-optimization/42575 * dce.c (word_dce_process_block): Renamed from byte_dce_process_block. Argument AU removed. All callers changed. Ignore artificial refs. Use return value of df_word_lr_simulate_defs to decide whether an insn is necessary. (fast_dce): Rename arg to WORD_LEVEL. (run_word_dce): Renamed from rest_of_handle_fast_byte_dce. No longer static. (pass_fast_rtl_byte_dce): Delete. * dce.h (run_word_dce): Declare. * df-core.c (df_print_word_regset): Renamed from df_print_byteregset. All callers changed. Simplify code to only deal with two-word regs. * df.h (DF_WORD_LR): Renamed from DF_BYTE_LR. (DF_WORD_LR_BB_INFO): Renamed from DF_BYTE_LR_BB_INFO. (DF_WORD_LR_IN): Renamed from DF_BYTE_LR_IN. (DF_WORD_LR_OUT): Renamed from DF_BYTE_LR_OUT. (struct df_word_lr_bb_info): Renamed from df_byte_lr_bb_info. (df_word_lr_mark_ref): Declare. (df_word_lr_add_problem, df_word_lr_mark_ref, df_word_lr_simulate_defs, df_word_lr_simulate_uses): Declare or rename from byte variants. (df_byte_lr_simulate_artificial_refs_at_top, df_byte_lr_simulate_artificial_refs_at_end, df_byte_lr_get_regno_start, df_byte_lr_get_regno_len, df_compute_accessed_bytes): Delete declarations. (df_word_lr_get_bb_info): Rename from df_byte_lr_get_bb_info. (enum df_mm): Delete. * df-byte-scan.c: Delete file. * df-problems.c (df_word_lr_problem_data): Renamed from df_byte_lr_problem_data, all members deleted except for WORD_LR_BITMAPS, which is renamed from BYTE_LR_BITMAPS. Uses changed. (df_word_lr_expand_bitmap, df_byte_lr_simulate_artificial_refs_at_top, df_byte_lr_simulate_artificial_refs_at_end, df_byte_lr_get_regno_start, df_byte_lr_get_regno_len, df_byte_lr_check_regs, df_byte_lr_confluence_0): Delete functions. (df_word_lr_free_bb_info): Renamed from df_byte_lr_free_bb_info; all callers changed. (df_word_lr_alloc): Renamed from df_byte_lr_alloc; all callers changed. Don't initialize members that were deleted, don't try to discover data about registers. Ignore hard regs. (df_word_lr_reset): Renamed from df_byte_lr_reset; all callers changed. (df_word_lr_mark_ref): New function. (df_word_lr_bb_local_compute): Renamed from df_byte_bb_lr_local_compute; all callers changed. Use df_word_lr_mark_ref. Assert that artificial refs don't include pseudos. Ignore hard registers. (df_word_lr_local_compute): Renamed from df_byte_lr_local_compute. Assert that exit block uses don't contain pseudos. (df_word_lr_init): Renamed from df_byte_lr_init; all callers changed. (df_word_lr_confluence_n): Renamed from df_byte_lr_confluence_n; all callers changed. Ignore hard regs. (df_word_lr_transfer_function): Renamed from df_byte_lr_transfer_function; all callers changed. (df_word_lr_free): Renamed from df_byte_lr_free; all callers changed. (df_word_lr_top_dump): Renamed from df_byte_lr_top_dump; all callers changed. (df_word_lr_bottom_dump): Renamed from df_byte_lr_bottom_dump; all callers changed. (problem_WORD_LR): Renamed from problem_BYTE_LR; uses changed; confluence operator 0 set to NULL. (df_word_lr_add_problem): Renamed from df_byte_lr_add_problem; all callers changed. (df_word_lr_simulate_defs): Renamed from df_byte_lr_simulate_defs. Return bool, true if bitmap changed or insn otherwise necessary. All callers changed. Simplify using df_word_lr_mark_ref. (df_word_lr_simulate_uses): Renamed from df_byte_lr_simulate_uses; all callers changed. Simplify using df_word_lr_mark_ref. * lower-subreg.c: Include "dce.h" (decompose_multiword_subregs): Call run_word_dce if df available. * Makefile.in (lower-subreg.o): Adjust dependencies. (df-byte-scan.o): Delete. * timevar.def (TV_DF_WORD_LR): Renamed from TV_DF_BYTE_LR. From-SVN: r162678 --- gcc/ChangeLog | 74 ++++++ gcc/Makefile.in | 5 +- gcc/dce.c | 112 ++------ gcc/dce.h | 1 + gcc/df-byte-scan.c | 340 ------------------------- gcc/df-core.c | 57 ++--- gcc/df-problems.c | 618 ++++++++++++--------------------------------- gcc/df.h | 52 ++-- gcc/lower-subreg.c | 4 + gcc/timevar.def | 2 +- 10 files changed, 300 insertions(+), 965 deletions(-) delete mode 100644 gcc/df-byte-scan.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 44353ab7ec8..e081dc26e68 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,77 @@ +2010-07-29 Bernd Schmidt + + PR rtl-optimization/42575 + * dce.c (word_dce_process_block): Renamed from byte_dce_process_block. + Argument AU removed. All callers changed. Ignore artificial refs. + Use return value of df_word_lr_simulate_defs to decide whether an insn + is necessary. + (fast_dce): Rename arg to WORD_LEVEL. + (run_word_dce): Renamed from rest_of_handle_fast_byte_dce. No longer + static. + (pass_fast_rtl_byte_dce): Delete. + * dce.h (run_word_dce): Declare. + * df-core.c (df_print_word_regset): Renamed from df_print_byteregset. + All callers changed. Simplify code to only deal with two-word regs. + * df.h (DF_WORD_LR): Renamed from DF_BYTE_LR. + (DF_WORD_LR_BB_INFO): Renamed from DF_BYTE_LR_BB_INFO. + (DF_WORD_LR_IN): Renamed from DF_BYTE_LR_IN. + (DF_WORD_LR_OUT): Renamed from DF_BYTE_LR_OUT. + (struct df_word_lr_bb_info): Renamed from df_byte_lr_bb_info. + (df_word_lr_mark_ref): Declare. + (df_word_lr_add_problem, df_word_lr_mark_ref, df_word_lr_simulate_defs, + df_word_lr_simulate_uses): Declare or rename from byte variants. + (df_byte_lr_simulate_artificial_refs_at_top, + df_byte_lr_simulate_artificial_refs_at_end, df_byte_lr_get_regno_start, + df_byte_lr_get_regno_len, df_compute_accessed_bytes): Delete + declarations. + (df_word_lr_get_bb_info): Rename from df_byte_lr_get_bb_info. + (enum df_mm): Delete. + * df-byte-scan.c: Delete file. + * df-problems.c (df_word_lr_problem_data): Renamed from + df_byte_lr_problem_data, all members deleted except for + WORD_LR_BITMAPS, which is renamed from BYTE_LR_BITMAPS. Uses changed. + (df_word_lr_expand_bitmap, df_byte_lr_simulate_artificial_refs_at_top, + df_byte_lr_simulate_artificial_refs_at_end, df_byte_lr_get_regno_start, + df_byte_lr_get_regno_len, df_byte_lr_check_regs, + df_byte_lr_confluence_0): Delete functions. + (df_word_lr_free_bb_info): Renamed from df_byte_lr_free_bb_info; all + callers changed. + (df_word_lr_alloc): Renamed from df_byte_lr_alloc; all callers changed. + Don't initialize members that were deleted, don't try to discover data + about registers. Ignore hard regs. + (df_word_lr_reset): Renamed from df_byte_lr_reset; all callers changed. + (df_word_lr_mark_ref): New function. + (df_word_lr_bb_local_compute): Renamed from + df_byte_bb_lr_local_compute; all callers changed. Use + df_word_lr_mark_ref. Assert that artificial refs don't include + pseudos. Ignore hard registers. + (df_word_lr_local_compute): Renamed from df_byte_lr_local_compute. + Assert that exit block uses don't contain pseudos. + (df_word_lr_init): Renamed from df_byte_lr_init; all callers changed. + (df_word_lr_confluence_n): Renamed from df_byte_lr_confluence_n; all + callers changed. Ignore hard regs. + (df_word_lr_transfer_function): Renamed from + df_byte_lr_transfer_function; all callers changed. + (df_word_lr_free): Renamed from df_byte_lr_free; all callers changed. + (df_word_lr_top_dump): Renamed from df_byte_lr_top_dump; all callers + changed. + (df_word_lr_bottom_dump): Renamed from df_byte_lr_bottom_dump; all + callers changed. + (problem_WORD_LR): Renamed from problem_BYTE_LR; uses changed; + confluence operator 0 set to NULL. + (df_word_lr_add_problem): Renamed from df_byte_lr_add_problem; all + callers changed. + (df_word_lr_simulate_defs): Renamed from df_byte_lr_simulate_defs. + Return bool, true if bitmap changed or insn otherwise necessary. + All callers changed. Simplify using df_word_lr_mark_ref. + (df_word_lr_simulate_uses): Renamed from df_byte_lr_simulate_uses; + all callers changed. Simplify using df_word_lr_mark_ref. + * lower-subreg.c: Include "dce.h" + (decompose_multiword_subregs): Call run_word_dce if df available. + * Makefile.in (lower-subreg.o): Adjust dependencies. + (df-byte-scan.o): Delete. + * timevar.def (TV_DF_WORD_LR): Renamed from TV_DF_BYTE_LR. + 2010-07-29 Richard Guenther * tree.c (build_vector): Assert that the vector constant diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 49724aaf4c5..a6b3460e948 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -1202,7 +1202,6 @@ OBJS-common = \ dce.o \ ddg.o \ debug.o \ - df-byte-scan.o \ df-core.o \ df-problems.o \ df-scan.o \ @@ -3167,8 +3166,6 @@ df-scan.o : df-scan.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ hard-reg-set.h $(BASIC_BLOCK_H) $(DF_H) $(BITMAP_H) sbitmap.h $(TIMEVAR_H) \ $(TM_P_H) $(FLAGS_H) $(TARGET_H) $(TARGET_DEF_H) $(TREE_H) output.h \ $(TREE_PASS_H) $(EMIT_RTL_H) -df-byte-scan.o : df-byte-scan.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ - $(TM_P_H) $(DF_H) output.h $(DBGCNT_H) regstat.o : regstat.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ $(TM_P_H) $(FLAGS_H) $(REGS_H) output.h $(EXCEPT_H) hard-reg-set.h \ $(BASIC_BLOCK_H) $(TIMEVAR_H) $(DF_H) @@ -3487,7 +3484,7 @@ dbgcnt.o: dbgcnt.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TOPLEV_H) $(DIAGNOSTIC_ lower-subreg.o : lower-subreg.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ $(MACHMODE_H) $(TM_H) $(RTL_H) $(TM_P_H) $(TIMEVAR_H) $(FLAGS_H) \ insn-config.h $(BASIC_BLOCK_H) $(RECOG_H) $(OBSTACK_H) $(BITMAP_H) \ - $(EXPR_H) $(EXCEPT_H) $(REGS_H) $(TREE_PASS_H) $(DF_H) + $(EXPR_H) $(EXCEPT_H) $(REGS_H) $(TREE_PASS_H) $(DF_H) dce.h target-globals.o : target-globals.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ $(TM_H) insn-config.h $(MACHMODE_H) $(GGC_H) $(TOPLEV_H) target-globals.h \ $(FLAGS_H) $(REGS_H) $(RTL_H) reload.h expmed.h $(EXPR_H) $(OPTABS_H) \ diff --git a/gcc/dce.c b/gcc/dce.c index ee18b58c4ab..19f8e42030d 100644 --- a/gcc/dce.c +++ b/gcc/dce.c @@ -767,12 +767,11 @@ struct rtl_opt_pass pass_ud_rtl_dce = artificial uses. */ static bool -byte_dce_process_block (basic_block bb, bool redo_out, bitmap au) +word_dce_process_block (basic_block bb, bool redo_out) { bitmap local_live = BITMAP_ALLOC (&dce_tmp_bitmap_obstack); rtx insn; bool block_changed; - df_ref *def_rec; if (redo_out) { @@ -781,8 +780,8 @@ byte_dce_process_block (basic_block bb, bool redo_out, bitmap au) set. */ edge e; edge_iterator ei; - df_confluence_function_n con_fun_n = df_byte_lr->problem->con_fun_n; - bitmap_clear (DF_BYTE_LR_OUT (bb)); + df_confluence_function_n con_fun_n = df_word_lr->problem->con_fun_n; + bitmap_clear (DF_WORD_LR_OUT (bb)); FOR_EACH_EDGE (e, ei, bb->succs) (*con_fun_n) (e); } @@ -790,76 +789,38 @@ byte_dce_process_block (basic_block bb, bool redo_out, bitmap au) if (dump_file) { fprintf (dump_file, "processing block %d live out = ", bb->index); - df_print_byte_regset (dump_file, DF_BYTE_LR_OUT (bb)); + df_print_word_regset (dump_file, DF_WORD_LR_OUT (bb)); } - bitmap_copy (local_live, DF_BYTE_LR_OUT (bb)); - - df_byte_lr_simulate_artificial_refs_at_end (bb, local_live); + bitmap_copy (local_live, DF_WORD_LR_OUT (bb)); FOR_BB_INSNS_REVERSE (bb, insn) if (INSN_P (insn)) { - /* The insn is needed if there is someone who uses the output. */ - for (def_rec = DF_INSN_DEFS (insn); *def_rec; def_rec++) - { - df_ref def = *def_rec; - unsigned int last; - unsigned int dregno = DF_REF_REGNO (def); - unsigned int start = df_byte_lr_get_regno_start (dregno); - unsigned int len = df_byte_lr_get_regno_len (dregno); - - unsigned int sb; - unsigned int lb; - /* This is one of the only places where DF_MM_MAY should - be used for defs. Need to make sure that we are - checking for all of the bits that may be used. */ - - if (!df_compute_accessed_bytes (def, DF_MM_MAY, &sb, &lb)) - { - start += sb; - len = lb - sb; - } - - if (bitmap_bit_p (au, dregno)) - { - mark_insn (insn, true); - goto quickexit; - } - - last = start + len; - while (start < last) - if (bitmap_bit_p (local_live, start++)) - { - mark_insn (insn, true); - goto quickexit; - } - } - - quickexit: - + bool any_changed; /* No matter if the instruction is needed or not, we remove any regno in the defs from the live set. */ - df_byte_lr_simulate_defs (insn, local_live); + any_changed = df_word_lr_simulate_defs (insn, local_live); + if (any_changed) + mark_insn (insn, true); /* On the other hand, we do not allow the dead uses to set anything in local_live. */ if (marked_insn_p (insn)) - df_byte_lr_simulate_uses (insn, local_live); + df_word_lr_simulate_uses (insn, local_live); if (dump_file) { fprintf (dump_file, "finished processing insn %d live out = ", INSN_UID (insn)); - df_print_byte_regset (dump_file, local_live); + df_print_word_regset (dump_file, local_live); } } - df_byte_lr_simulate_artificial_refs_at_top (bb, local_live); - - block_changed = !bitmap_equal_p (local_live, DF_BYTE_LR_IN (bb)); + block_changed = !bitmap_equal_p (local_live, DF_WORD_LR_IN (bb)); if (block_changed) - bitmap_copy (DF_BYTE_LR_IN (bb), local_live); + bitmap_copy (DF_WORD_LR_IN (bb), local_live); + BITMAP_FREE (local_live); return block_changed; } @@ -938,12 +899,12 @@ dce_process_block (basic_block bb, bool redo_out, bitmap au) } -/* Perform fast DCE once initialization is done. If BYTE_LEVEL is - true, use the byte level dce, otherwise do it at the pseudo +/* Perform fast DCE once initialization is done. If WORD_LEVEL is + true, use the word level dce, otherwise do it at the pseudo level. */ static void -fast_dce (bool byte_level) +fast_dce (bool word_level) { int *postorder = df_get_postorder (DF_BACKWARD); int n_blocks = df_get_n_blocks (DF_BACKWARD); @@ -985,10 +946,9 @@ fast_dce (bool byte_level) continue; } - if (byte_level) + if (word_level) local_changed - = byte_dce_process_block (bb, bitmap_bit_p (redo_out, index), - bb_has_eh_pred (bb) ? au_eh : au); + = word_dce_process_block (bb, bitmap_bit_p (redo_out, index)); else local_changed = dce_process_block (bb, bitmap_bit_p (redo_out, index), @@ -1028,8 +988,8 @@ fast_dce (bool byte_level) to redo the dataflow equations for the blocks that had a change at the top of the block. Then we need to redo the iteration. */ - if (byte_level) - df_analyze_problem (df_byte_lr, all_blocks, postorder, n_blocks); + if (word_level) + df_analyze_problem (df_word_lr, all_blocks, postorder, n_blocks); else df_analyze_problem (df_lr, all_blocks, postorder, n_blocks); @@ -1062,14 +1022,15 @@ rest_of_handle_fast_dce (void) /* Fast byte level DCE. */ -static unsigned int -rest_of_handle_fast_byte_dce (void) +void +run_word_dce (void) { - df_byte_lr_add_problem (); + timevar_push (TV_DCE); + df_word_lr_add_problem (); init_dce (true); fast_dce (true); fini_dce (true); - return 0; + timevar_pop (TV_DCE); } @@ -1139,24 +1100,3 @@ struct rtl_opt_pass pass_fast_rtl_dce = TODO_ggc_collect /* todo_flags_finish */ } }; - -struct rtl_opt_pass pass_fast_rtl_byte_dce = -{ - { - RTL_PASS, - "byte-dce", /* name */ - gate_fast_dce, /* gate */ - rest_of_handle_fast_byte_dce, /* execute */ - NULL, /* sub */ - NULL, /* next */ - 0, /* static_pass_number */ - TV_DCE, /* tv_id */ - 0, /* properties_required */ - 0, /* properties_provided */ - 0, /* properties_destroyed */ - 0, /* todo_flags_start */ - TODO_dump_func | - TODO_df_finish | TODO_verify_rtl_sharing | - TODO_ggc_collect /* todo_flags_finish */ - } -}; diff --git a/gcc/dce.h b/gcc/dce.h index 2635d49922b..341588c7eb5 100644 --- a/gcc/dce.h +++ b/gcc/dce.h @@ -20,6 +20,7 @@ along with GCC; see the file COPYING3. If not see #ifndef GCC_DCE_H #define GCC_DCE_H +extern void run_word_dce (void); extern void run_fast_dce (void); extern void run_fast_df_dce (void); diff --git a/gcc/df-byte-scan.c b/gcc/df-byte-scan.c deleted file mode 100644 index 8271465041e..00000000000 --- a/gcc/df-byte-scan.c +++ /dev/null @@ -1,340 +0,0 @@ -/* Scanning of rtl byte level scanning for dataflow analysis. - Copyright (C) 2008 Free Software Foundation, Inc. - Contributed by Kenneth Zadeck (zadeck@naturalbridge.com). - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free -Software Foundation; either version 3, or (at your option) any later -version. - -GCC is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -for more details. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING3. If not see -. */ - -#include "config.h" -#include "system.h" -#include "coretypes.h" -#include "tm.h" -#include "rtl.h" -#include "tm_p.h" -#include "df.h" -#include "output.h" -#include "dbgcnt.h" - -/* The following suite of functions provides bytewise modeling of REFs - which are struct df_ref. START_BYTE and LAST_BYTE are returned. - These can be used as indexes into bitmaps. The indexes are - normalized so that 0 is the lowest numbered byte, of the inner - register according to the natural ordering of the machine. - - This code is designed to be used in backwards scans (which is, of - course, the way all dataflow scanning should really be done). It - would require a lot of reworking of the api to make it work in a - forwards scanning world. */ - - -/* Helper for df_compute_accessed_bytes. Ref is some sort of extract. - Return true if this effects the entire reg in REF. Return false if - otherwise and set START_BYTE and LAST_BYTE. See the description of - df_compute_accessed_bytes for a description of MM. */ - -static bool -df_compute_accessed_bytes_extract (df_ref ref, - enum df_mm mm , - unsigned int *start_byte, - unsigned int *last_byte) -{ - int start; - int last; - rtx reg = DF_REF_REG (ref); - enum machine_mode m1; - int m1_size; - enum machine_mode m2; - int m2_size; - - /* (*_extract:M1 (reg:M2 X) WIDTH POS) - (*_extract:M1 (subreg:M1 (reg:M2 X N) WIDTH POS) - - This is a bitfield extraction. The assignment clobbers/extracts - exactly the bits named by WIDTH and POS and does not affect the - other bits in register X. It is also technically possible that - the bits asked for are longer than units per word. */ - - int offset = DF_REF_EXTRACT_OFFSET (ref); - int width = DF_REF_EXTRACT_WIDTH (ref); - - if (width == -1 || offset == -1) - return true; - - m1 = DF_REF_EXTRACT_MODE (ref); - m1_size = GET_MODE_SIZE (m1); - - gcc_assert (m1_size <= UNITS_PER_WORD); - - /* There is nothing to do if this is a pure big or small endian - machine, but if the machine is a pastiche, we have to convert the - bit offsets into byte offsets. This is only possible because we - do not care about individual bits because this conversion may - make the bits non-contiguous. */ - if (BYTES_BIG_ENDIAN != BITS_BIG_ENDIAN) - offset = GET_MODE_BITSIZE (m1_size) - (offset + width); - - /* The offset is now in the same order as the subreg_byte. */ - if (GET_CODE (reg) == SUBREG) - { - m2 = GET_MODE (SUBREG_REG (reg)); - m2_size = GET_MODE_SIZE (m2); - if (m1_size > m2_size) - /* If it is paradoxical, subreg_byte will be zero. */ - offset -= subreg_lowpart_offset (m2, m1) * BITS_PER_UNIT; - else - offset += SUBREG_BYTE (reg) * BITS_PER_UNIT; - } - else - { - m2 = GET_MODE (reg); - m2_size = GET_MODE_SIZE (m2); - } - - if (mm == DF_MM_MUST) - { - /* For defs (generally), count the byte only if the whole byte - is touched. */ - start = (offset + BITS_PER_UNIT - 1) / BITS_PER_UNIT; - last = (width + offset) / BITS_PER_UNIT; - - /* In the case where there is nothing, start may be one larger - than last, we canonize this to return zeros. This keeps - computations of length from being negative. */ - if (start >= last) - { - start = 0; - last = 0; - } - } - else - { - /* For uses (generally), count the byte if any part of the byte - is touched. */ - start = offset / BITS_PER_UNIT; - last = (width + offset + BITS_PER_UNIT - 1) / BITS_PER_UNIT; - } - - /* Paradoxical truncation. */ - if (start < 0) - start = 0; - if (last > m2_size) - last = m2_size; - - if (dump_file) - fprintf (dump_file, " cpb extract regno=%d start=%d last=%d\n", - DF_REF_REGNO (ref), start, last); - - *start_byte = start; - *last_byte = last; - return false; -} - - -/* Helper for df_compute_accessed_bytes. Ref is a strict_low_part. - Return true if this effects the entire reg in REF. Return false if - otherwise and set START_BYTE and LAST_BYTE. */ - -static bool -df_compute_accessed_bytes_strict_low_part (df_ref ref, - unsigned int *start_byte, - unsigned int *last_byte) -{ - int start; - int last; - rtx reg = DF_REF_REG (ref); - enum machine_mode m1; - int m1_size; - enum machine_mode m2; - int m2_size; - int offset; - - /* In order to accommodate multiword subregs of a hardreg, df_scan - eats the subreg and it can only be found from the loc. */ - if (REG_P (reg)) - reg = *(DF_REF_LOC (ref)); - - m1 = GET_MODE (reg); - m1_size = GET_MODE_SIZE (m1); - m2 = GET_MODE (SUBREG_REG (reg)); - m2_size = GET_MODE_SIZE (m2); - offset = SUBREG_BYTE (reg); - - /* It does not seem to be meaningful to apply a strict_low_part of a - paradoxical register. */ - gcc_assert (m1_size <= m2_size); - - /* (set (strict_low_part (subreg:M1 (reg:M2 X) N)) ...) - - This is a bitfield insertion. The assignment clobbers exactly the - bits named by the subreg--the M1 bits at position N. It is also - technically possible that the bits asked for are longer than units - per word. */ - - start = offset; - last = offset + m1_size; - - if (dump_file) - fprintf (dump_file, " cpb strict low part regno=%d start=%d last=%d\n", - DF_REF_REGNO (ref), start, last); - - *start_byte = start; - *last_byte = last; - return false; -} - -/* Helper for df_compute_accessed_bytes. Ref is a naked subreg. - Return true if this effects the entire reg in REF. Return false if - otherwise and set START_BYTE and LAST_BYTE. */ - -static bool -df_compute_accessed_bytes_subreg (df_ref ref, unsigned int *start_byte, - unsigned int *last_byte) - -{ - /* (subreg:M1 (reg:M2 X) N) */ - int start; - int last; - rtx reg = DF_REF_REG (ref); - - enum machine_mode m1; - int m1_size; - enum machine_mode m2; - int m2_size; - - /* In order to accommodate multiword subregs of a hardreg, df_scan - eats the subreg and it can only be found from the loc. */ - if (REG_P (reg)) - reg = *(DF_REF_LOC (ref)); - - m1 = GET_MODE (reg); - m1_size = GET_MODE_SIZE (m1); - m2 = GET_MODE (SUBREG_REG (reg)); - m2_size = GET_MODE_SIZE (m2); - - /* A simple paradoxical subreg just accesses the entire inner reg. */ - if (m1_size >= m2_size) - return true; - - /* Defs and uses are different in the amount of the reg that touch. */ - if (DF_REF_REG_DEF_P (ref)) - { - /* This is an lvalue. */ - - if (m2_size > UNITS_PER_WORD) - { - /* The assignment clobbers UNITS_PER_WORD segments of X. - Look at the bytes named by the subreg, and expand it to - cover a UNITS_PER_WORD part of register X. That part of - register X is clobbered, the rest is not. - - E.g., (subreg:SI (reg:DI X) 0), where UNITS_PER_WORD is the - size of SImode, clobbers the first SImode part of X, and does - not affect the second SImode part. - - E.g., (subreg:QI (reg:DI X) 0), where UNITS_PER_WORD is the - size of SImode, clobbers the first SImode part of X, and does - not affect the second SImode part. Here the QImode byte is - expanded to a UNITS_PER_WORD portion of the register for - purposes of determining what is clobbered. - - If this is an rvalue, then it touches just the bytes that it - talks about. */ - int offset = SUBREG_BYTE (reg); - - start = offset & ~(UNITS_PER_WORD - 1); - last = (offset + m1_size + UNITS_PER_WORD - 1) - & ~(UNITS_PER_WORD - 1); - } - else - /* Whole register size M2 equal to or smaller than - UNITS_PER_WORD The assignment clobbers the entire register - X. */ - return true; - } - else - { - /* This is an rvalue. It touches just the bytes they explicitly - mentioned. */ - int offset = SUBREG_BYTE (reg); - start = offset; - last = start + m1_size; - } - - if (dump_file) - fprintf (dump_file, " cpb subreg regno=%d start=%d last=%d\n", - DF_REF_REGNO (ref), start, last); - - *start_byte = start; - *last_byte = last; - return false; -} - - -/* Compute the set of affected bytes by a store to a pseudo to REF. - MM is either DF_MM_MAY or DF_MM_MUST. This is only relevant for - the extracts which are not aligned to byte boundaries. The - DF_MM_MAY returns all of the bytes that any bit is set in and the - DF_MM_MUST returns only the bytes that are completely covered. In - general DF_MM_MAY is used for uses and DF_MM_MUST is used for defs, - but there are exceptions such as the inner loop of the byte level - dead code eliminator which needs DF_MM_MAY for the defs to see if - it any possible bit could be used. - - If the store is to the whole register, just return TRUE, if it is - to part of the register, return FALSE and set START_BYTE and - LAST_BYTE properly. In the case where fabricated uses are passed - in, START_BYTE and LAST_BYTE are set to 0 and false is returned. - This means that this use can be ignored. */ - -bool -df_compute_accessed_bytes (df_ref ref, enum df_mm mm, - unsigned int *start_byte, - unsigned int *last_byte) -{ - if (!dbg_cnt (df_byte_scan)) - return true; - - if (!DF_REF_REG_DEF_P (ref) - && DF_REF_FLAGS_IS_SET (ref, DF_REF_READ_WRITE)) - { - if (DF_REF_FLAGS_IS_SET (ref, DF_REF_PRE_POST_MODIFY)) - /* Pre/post modify/inc/dec always read and write the entire - reg. */ - return true; - else - { - /* DF_REF_READ_WRITE on a use (except for the - DF_REF_PRE_POST_MODIFY) means that this use is fabricated - from a def that is a partial set to a multiword reg. - Here, we only model those cases precisely so the only one - to consider is the use put on a auto inc and dec - insns. */ - *start_byte = 0; - *last_byte = 0; - return false; - } - } - - if (DF_REF_FLAGS_IS_SET (ref, DF_REF_SIGN_EXTRACT | DF_REF_ZERO_EXTRACT)) - return df_compute_accessed_bytes_extract (ref, mm, start_byte, last_byte); - else if (DF_REF_FLAGS_IS_SET (ref, DF_REF_STRICT_LOW_PART)) - return df_compute_accessed_bytes_strict_low_part (ref, - start_byte, last_byte); - else if (GET_CODE (DF_REF_REG (ref)) == SUBREG) - return df_compute_accessed_bytes_subreg (ref, start_byte, last_byte); - return true; -} - diff --git a/gcc/df-core.c b/gcc/df-core.c index 8eaef6d3557..181c1e7ce22 100644 --- a/gcc/df-core.c +++ b/gcc/df-core.c @@ -1919,58 +1919,33 @@ df_print_regset (FILE *file, bitmap r) debugging dump. */ void -df_print_byte_regset (FILE *file, bitmap r) +df_print_word_regset (FILE *file, bitmap r) { unsigned int max_reg = max_reg_num (); - bitmap_iterator bi; if (r == NULL) fputs (" (nil)", file); else { unsigned int i; - for (i = 0; i < max_reg; i++) + for (i = FIRST_PSEUDO_REGISTER; i < max_reg; i++) { - unsigned int first = df_byte_lr_get_regno_start (i); - unsigned int len = df_byte_lr_get_regno_len (i); - - if (len > 1) + bool found = (bitmap_bit_p (r, 2 * i) + || bitmap_bit_p (r, 2 * i + 1)); + if (found) { - bool found = false; - unsigned int j; - - EXECUTE_IF_SET_IN_BITMAP (r, first, j, bi) - { - found = j < first + len; - break; - } - if (found) - { - const char * sep = ""; - fprintf (file, " %d", i); - if (i < FIRST_PSEUDO_REGISTER) - fprintf (file, " [%s]", reg_names[i]); - fprintf (file, "("); - EXECUTE_IF_SET_IN_BITMAP (r, first, j, bi) - { - if (j > first + len - 1) - break; - fprintf (file, "%s%d", sep, j-first); - sep = ", "; - } - fprintf (file, ")"); - } + int word; + const char * sep = ""; + fprintf (file, " %d", i); + fprintf (file, "("); + for (word = 0; word < 2; word++) + if (bitmap_bit_p (r, 2 * i + word)) + { + fprintf (file, "%s%d", sep, word); + sep = ", "; + } + fprintf (file, ")"); } - else - { - if (bitmap_bit_p (r, first)) - { - fprintf (file, " %d", i); - if (i < FIRST_PSEUDO_REGISTER) - fprintf (file, " [%s]", reg_names[i]); - } - } - } } fprintf (file, "\n"); diff --git a/gcc/df-problems.c b/gcc/df-problems.c index 3b3f4262503..d0d0ea71608 100644 --- a/gcc/df-problems.c +++ b/gcc/df-problems.c @@ -2286,84 +2286,31 @@ df_chain_add_problem (unsigned int chain_flags) /*---------------------------------------------------------------------------- - BYTE LEVEL LIVE REGISTERS + WORD LEVEL LIVE REGISTERS Find the locations in the function where any use of a pseudo can reach in the backwards direction. In and out bitvectors are built - for each basic block. There are two mapping functions, - df_byte_lr_get_regno_start and df_byte_lr_get_regno_len that are - used to map regnos into bit vector positions. - - This problem differs from the regular df_lr function in the way - that subregs, *_extracts and strict_low_parts are handled. In lr - these are consider partial kills, here, the exact set of bytes is - modeled. Note that any reg that has none of these operations is - only modeled with a single bit since all operations access the - entire register. - - This problem is more brittle that the regular lr. It currently can - be used in dce incrementally, but cannot be used in an environment - where insns are created or modified. The problem is that the - mapping of regnos to bitmap positions is relatively compact, in - that if a pseudo does not do any of the byte wise operations, only - one slot is allocated, rather than a slot for each byte. If insn - are created, where a subreg is used for a reg that had no subregs, - the mapping would be wrong. Likewise, there are no checks to see - that new pseudos have been added. These issues could be addressed - by adding a problem specific flag to not use the compact mapping, - if there was a need to do so. + for each basic block. We only track pseudo registers that have a + size of 2 * UNITS_PER_WORD; bitmaps are indexed by 2 * regno and + contain two bits corresponding to each of the subwords. ----------------------------------------------------------------------------*/ /* Private data used to verify the solution for this problem. */ -struct df_byte_lr_problem_data +struct df_word_lr_problem_data { - /* Expanded versions of bitvectors used in lr. */ - bitmap_head invalidated_by_call; - bitmap_head hardware_regs_used; - - /* Indexed by regno, this is true if there are subregs, extracts or - strict_low_parts for this regno. */ - bitmap_head needs_expansion; - - /* The start position and len for each regno in the various bit - vectors. */ - unsigned int* regno_start; - unsigned int* regno_len; /* An obstack for the bitmaps we need for this problem. */ - bitmap_obstack byte_lr_bitmaps; + bitmap_obstack word_lr_bitmaps; }; -/* Get the starting location for REGNO in the df_byte_lr bitmaps. */ - -int -df_byte_lr_get_regno_start (unsigned int regno) -{ - struct df_byte_lr_problem_data *problem_data - = (struct df_byte_lr_problem_data *)df_byte_lr->problem_data;; - return problem_data->regno_start[regno]; -} - - -/* Get the len for REGNO in the df_byte_lr bitmaps. */ - -int -df_byte_lr_get_regno_len (unsigned int regno) -{ - struct df_byte_lr_problem_data *problem_data - = (struct df_byte_lr_problem_data *)df_byte_lr->problem_data;; - return problem_data->regno_len[regno]; -} - - /* Free basic block info. */ static void -df_byte_lr_free_bb_info (basic_block bb ATTRIBUTE_UNUSED, +df_word_lr_free_bb_info (basic_block bb ATTRIBUTE_UNUSED, void *vbb_info) { - struct df_byte_lr_bb_info *bb_info = (struct df_byte_lr_bb_info *) vbb_info; + struct df_word_lr_bb_info *bb_info = (struct df_word_lr_bb_info *) vbb_info; if (bb_info) { bitmap_clear (&bb_info->use); @@ -2374,65 +2321,21 @@ df_byte_lr_free_bb_info (basic_block bb ATTRIBUTE_UNUSED, } -/* Check all of the refs in REF_REC to see if any of them are - extracts, subregs or strict_low_parts. */ - -static void -df_byte_lr_check_regs (df_ref *ref_rec) -{ - struct df_byte_lr_problem_data *problem_data - = (struct df_byte_lr_problem_data *)df_byte_lr->problem_data; - - for (; *ref_rec; ref_rec++) - { - df_ref ref = *ref_rec; - if (DF_REF_FLAGS_IS_SET (ref, DF_REF_SIGN_EXTRACT - | DF_REF_ZERO_EXTRACT - | DF_REF_STRICT_LOW_PART) - || GET_CODE (DF_REF_REG (ref)) == SUBREG) - bitmap_set_bit (&problem_data->needs_expansion, DF_REF_REGNO (ref)); - } -} - - -/* Expand bitmap SRC which is indexed by regno to DEST which is indexed by - regno_start and regno_len. */ - -static void -df_byte_lr_expand_bitmap (bitmap dest, bitmap src) -{ - struct df_byte_lr_problem_data *problem_data - = (struct df_byte_lr_problem_data *)df_byte_lr->problem_data; - bitmap_iterator bi; - unsigned int i; - - bitmap_clear (dest); - EXECUTE_IF_SET_IN_BITMAP (src, 0, i, bi) - { - bitmap_set_range (dest, problem_data->regno_start[i], - problem_data->regno_len[i]); - } -} - - -/* Allocate or reset bitmaps for DF_BYTE_LR blocks. The solution bits are +/* Allocate or reset bitmaps for DF_WORD_LR blocks. The solution bits are not touched unless the block is new. */ static void -df_byte_lr_alloc (bitmap all_blocks ATTRIBUTE_UNUSED) +df_word_lr_alloc (bitmap all_blocks ATTRIBUTE_UNUSED) { unsigned int bb_index; bitmap_iterator bi; basic_block bb; - unsigned int regno; - unsigned int index = 0; - unsigned int max_reg = max_reg_num(); - struct df_byte_lr_problem_data *problem_data - = XNEW (struct df_byte_lr_problem_data); + struct df_word_lr_problem_data *problem_data + = XNEW (struct df_word_lr_problem_data); - df_byte_lr->problem_data = problem_data; + df_word_lr->problem_data = problem_data; - df_grow_bb_info (df_byte_lr); + df_grow_bb_info (df_word_lr); /* Create the mapping from regnos to slots. This does not change unless the problem is destroyed and recreated. In particular, if @@ -2440,58 +2343,17 @@ df_byte_lr_alloc (bitmap all_blocks ATTRIBUTE_UNUSED) want to redo the mapping because this would invalidate everything else. */ - bitmap_obstack_initialize (&problem_data->byte_lr_bitmaps); - problem_data->regno_start = XNEWVEC (unsigned int, max_reg); - problem_data->regno_len = XNEWVEC (unsigned int, max_reg); - bitmap_initialize (&problem_data->hardware_regs_used, - &problem_data->byte_lr_bitmaps); - bitmap_initialize (&problem_data->invalidated_by_call, - &problem_data->byte_lr_bitmaps); - bitmap_initialize (&problem_data->needs_expansion, - &problem_data->byte_lr_bitmaps); + bitmap_obstack_initialize (&problem_data->word_lr_bitmaps); - /* Discover which regno's use subregs, extracts or - strict_low_parts. */ FOR_EACH_BB (bb) + bitmap_set_bit (df_word_lr->out_of_date_transfer_functions, bb->index); + + bitmap_set_bit (df_word_lr->out_of_date_transfer_functions, ENTRY_BLOCK); + bitmap_set_bit (df_word_lr->out_of_date_transfer_functions, EXIT_BLOCK); + + EXECUTE_IF_SET_IN_BITMAP (df_word_lr->out_of_date_transfer_functions, 0, bb_index, bi) { - rtx insn; - FOR_BB_INSNS (bb, insn) - { - if (INSN_P (insn)) - { - struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn); - df_byte_lr_check_regs (DF_INSN_INFO_DEFS (insn_info)); - df_byte_lr_check_regs (DF_INSN_INFO_USES (insn_info)); - } - } - bitmap_set_bit (df_byte_lr->out_of_date_transfer_functions, bb->index); - } - - bitmap_set_bit (df_byte_lr->out_of_date_transfer_functions, ENTRY_BLOCK); - bitmap_set_bit (df_byte_lr->out_of_date_transfer_functions, EXIT_BLOCK); - - /* Allocate the slots for each regno. */ - for (regno = 0; regno < max_reg; regno++) - { - int len; - problem_data->regno_start[regno] = index; - if (bitmap_bit_p (&problem_data->needs_expansion, regno)) - len = GET_MODE_SIZE (GET_MODE (regno_reg_rtx[regno])); - else - len = 1; - - problem_data->regno_len[regno] = len; - index += len; - } - - df_byte_lr_expand_bitmap (&problem_data->hardware_regs_used, - &df->hardware_regs_used); - df_byte_lr_expand_bitmap (&problem_data->invalidated_by_call, - regs_invalidated_by_call_regset); - - EXECUTE_IF_SET_IN_BITMAP (df_byte_lr->out_of_date_transfer_functions, 0, bb_index, bi) - { - struct df_byte_lr_bb_info *bb_info = df_byte_lr_get_bb_info (bb_index); + struct df_word_lr_bb_info *bb_info = df_word_lr_get_bb_info (bb_index); /* When bitmaps are already initialized, just clear them. */ if (bb_info->use.obstack) @@ -2501,74 +2363,109 @@ df_byte_lr_alloc (bitmap all_blocks ATTRIBUTE_UNUSED) } else { - bitmap_initialize (&bb_info->use, &problem_data->byte_lr_bitmaps); - bitmap_initialize (&bb_info->def, &problem_data->byte_lr_bitmaps); - bitmap_initialize (&bb_info->in, &problem_data->byte_lr_bitmaps); - bitmap_initialize (&bb_info->out, &problem_data->byte_lr_bitmaps); + bitmap_initialize (&bb_info->use, &problem_data->word_lr_bitmaps); + bitmap_initialize (&bb_info->def, &problem_data->word_lr_bitmaps); + bitmap_initialize (&bb_info->in, &problem_data->word_lr_bitmaps); + bitmap_initialize (&bb_info->out, &problem_data->word_lr_bitmaps); } } - df_byte_lr->optional_p = true; + df_word_lr->optional_p = true; } /* Reset the global solution for recalculation. */ static void -df_byte_lr_reset (bitmap all_blocks) +df_word_lr_reset (bitmap all_blocks) { unsigned int bb_index; bitmap_iterator bi; EXECUTE_IF_SET_IN_BITMAP (all_blocks, 0, bb_index, bi) { - struct df_byte_lr_bb_info *bb_info = df_byte_lr_get_bb_info (bb_index); + struct df_word_lr_bb_info *bb_info = df_word_lr_get_bb_info (bb_index); gcc_assert (bb_info); bitmap_clear (&bb_info->in); bitmap_clear (&bb_info->out); } } +/* Examine REF, and if it is for a reg we're interested in, set or + clear the bits corresponding to its subwords from the bitmap + according to IS_SET. LIVE is the bitmap we should update. We do + not track hard regs or pseudos of any size other than 2 * + UNITS_PER_WORD. + We return true if we changed the bitmap, or if we encountered a register + we're not tracking. */ + +bool +df_word_lr_mark_ref (df_ref ref, bool is_set, regset live) +{ + rtx orig_reg = DF_REF_REG (ref); + rtx reg = orig_reg; + enum machine_mode reg_mode; + unsigned regno; + /* Left at -1 for whole accesses. */ + int which_subword = -1; + bool changed = false; + + if (GET_CODE (reg) == SUBREG) + reg = SUBREG_REG (orig_reg); + regno = REGNO (reg); + reg_mode = GET_MODE (reg); + if (regno < FIRST_PSEUDO_REGISTER + || GET_MODE_SIZE (reg_mode) != 2 * UNITS_PER_WORD) + return true; + + if (GET_CODE (orig_reg) == SUBREG + && df_read_modify_subreg_p (orig_reg)) + { + gcc_assert (DF_REF_FLAGS_IS_SET (ref, DF_REF_PARTIAL)); + if (subreg_lowpart_p (orig_reg)) + which_subword = 0; + else + which_subword = 1; + } + if (is_set) + { + if (which_subword != 1) + changed |= bitmap_set_bit (live, regno * 2); + if (which_subword != 0) + changed |= bitmap_set_bit (live, regno * 2 + 1); + } + else + { + if (which_subword != 1) + changed |= bitmap_clear_bit (live, regno * 2); + if (which_subword != 0) + changed |= bitmap_clear_bit (live, regno * 2 + 1); + } + return changed; +} /* Compute local live register info for basic block BB. */ static void -df_byte_lr_bb_local_compute (unsigned int bb_index) +df_word_lr_bb_local_compute (unsigned int bb_index) { - struct df_byte_lr_problem_data *problem_data - = (struct df_byte_lr_problem_data *)df_byte_lr->problem_data; basic_block bb = BASIC_BLOCK (bb_index); - struct df_byte_lr_bb_info *bb_info = df_byte_lr_get_bb_info (bb_index); + struct df_word_lr_bb_info *bb_info = df_word_lr_get_bb_info (bb_index); rtx insn; df_ref *def_rec; df_ref *use_rec; - /* Process the registers set in an exception handler. */ + /* Ensure that artificial refs don't contain references to pseudos. */ for (def_rec = df_get_artificial_defs (bb_index); *def_rec; def_rec++) { df_ref def = *def_rec; - if ((DF_REF_FLAGS (def) & DF_REF_AT_TOP) == 0) - { - unsigned int dregno = DF_REF_REGNO (def); - unsigned int start = problem_data->regno_start[dregno]; - unsigned int len = problem_data->regno_len[dregno]; - bitmap_set_range (&bb_info->def, start, len); - bitmap_clear_range (&bb_info->use, start, len); - } + gcc_assert (DF_REF_REGNO (def) < FIRST_PSEUDO_REGISTER); } - /* Process the hardware registers that are always live. */ for (use_rec = df_get_artificial_uses (bb_index); *use_rec; use_rec++) { df_ref use = *use_rec; - /* Add use to set of uses in this BB. */ - if ((DF_REF_FLAGS (use) & DF_REF_AT_TOP) == 0) - { - unsigned int uregno = DF_REF_REGNO (use); - unsigned int start = problem_data->regno_start[uregno]; - unsigned int len = problem_data->regno_len[uregno]; - bitmap_set_range (&bb_info->use, start, len); - } + gcc_assert (DF_REF_REGNO (use) < FIRST_PSEUDO_REGISTER); } FOR_BB_INSNS_REVERSE (bb, insn) @@ -2577,7 +2474,6 @@ df_byte_lr_bb_local_compute (unsigned int bb_index) if (!INSN_P (insn)) continue; - for (def_rec = DF_INSN_UID_DEFS (uid); *def_rec; def_rec++) { df_ref def = *def_rec; @@ -2585,164 +2481,80 @@ df_byte_lr_bb_local_compute (unsigned int bb_index) not kill the other defs that reach here. */ if (!(DF_REF_FLAGS (def) & (DF_REF_CONDITIONAL))) { - unsigned int dregno = DF_REF_REGNO (def); - unsigned int start = problem_data->regno_start[dregno]; - unsigned int len = problem_data->regno_len[dregno]; - unsigned int sb; - unsigned int lb; - if (!df_compute_accessed_bytes (def, DF_MM_MUST, &sb, &lb)) - { - start += sb; - len = lb - sb; - } - if (len) - { - bitmap_set_range (&bb_info->def, start, len); - bitmap_clear_range (&bb_info->use, start, len); - } + df_word_lr_mark_ref (def, true, &bb_info->def); + df_word_lr_mark_ref (def, false, &bb_info->use); } } - for (use_rec = DF_INSN_UID_USES (uid); *use_rec; use_rec++) { df_ref use = *use_rec; - unsigned int uregno = DF_REF_REGNO (use); - unsigned int start = problem_data->regno_start[uregno]; - unsigned int len = problem_data->regno_len[uregno]; - unsigned int sb; - unsigned int lb; - if (!df_compute_accessed_bytes (use, DF_MM_MAY, &sb, &lb)) - { - start += sb; - len = lb - sb; - } - /* Add use to set of uses in this BB. */ - if (len) - bitmap_set_range (&bb_info->use, start, len); + df_word_lr_mark_ref (use, true, &bb_info->use); } } - - /* Process the registers set in an exception handler or the hard - frame pointer if this block is the target of a non local - goto. */ - for (def_rec = df_get_artificial_defs (bb_index); *def_rec; def_rec++) - { - df_ref def = *def_rec; - if (DF_REF_FLAGS (def) & DF_REF_AT_TOP) - { - unsigned int dregno = DF_REF_REGNO (def); - unsigned int start = problem_data->regno_start[dregno]; - unsigned int len = problem_data->regno_len[dregno]; - bitmap_set_range (&bb_info->def, start, len); - bitmap_clear_range (&bb_info->use, start, len); - } - } - -#ifdef EH_USES - /* Process the uses that are live into an exception handler. */ - for (use_rec = df_get_artificial_uses (bb_index); *use_rec; use_rec++) - { - df_ref use = *use_rec; - /* Add use to set of uses in this BB. */ - if (DF_REF_FLAGS (use) & DF_REF_AT_TOP) - { - unsigned int uregno = DF_REF_REGNO (use); - unsigned int start = problem_data->regno_start[uregno]; - unsigned int len = problem_data->regno_len[uregno]; - bitmap_set_range (&bb_info->use, start, len); - } - } -#endif } /* Compute local live register info for each basic block within BLOCKS. */ static void -df_byte_lr_local_compute (bitmap all_blocks ATTRIBUTE_UNUSED) +df_word_lr_local_compute (bitmap all_blocks ATTRIBUTE_UNUSED) { unsigned int bb_index; bitmap_iterator bi; - EXECUTE_IF_SET_IN_BITMAP (df_byte_lr->out_of_date_transfer_functions, 0, bb_index, bi) + EXECUTE_IF_SET_IN_BITMAP (df_word_lr->out_of_date_transfer_functions, 0, bb_index, bi) { if (bb_index == EXIT_BLOCK) { - /* The exit block is special for this problem and its bits are - computed from thin air. */ - struct df_byte_lr_bb_info *bb_info = df_byte_lr_get_bb_info (EXIT_BLOCK); - df_byte_lr_expand_bitmap (&bb_info->use, df->exit_block_uses); + unsigned regno; + bitmap_iterator bi; + EXECUTE_IF_SET_IN_BITMAP (df->exit_block_uses, FIRST_PSEUDO_REGISTER, + regno, bi) + gcc_unreachable (); } else - df_byte_lr_bb_local_compute (bb_index); + df_word_lr_bb_local_compute (bb_index); } - bitmap_clear (df_byte_lr->out_of_date_transfer_functions); + bitmap_clear (df_word_lr->out_of_date_transfer_functions); } /* Initialize the solution vectors. */ static void -df_byte_lr_init (bitmap all_blocks) +df_word_lr_init (bitmap all_blocks) { unsigned int bb_index; bitmap_iterator bi; EXECUTE_IF_SET_IN_BITMAP (all_blocks, 0, bb_index, bi) { - struct df_byte_lr_bb_info *bb_info = df_byte_lr_get_bb_info (bb_index); + struct df_word_lr_bb_info *bb_info = df_word_lr_get_bb_info (bb_index); bitmap_copy (&bb_info->in, &bb_info->use); bitmap_clear (&bb_info->out); } } -/* Confluence function that processes infinite loops. This might be a - noreturn function that throws. And even if it isn't, getting the - unwind info right helps debugging. */ -static void -df_byte_lr_confluence_0 (basic_block bb) -{ - struct df_byte_lr_problem_data *problem_data - = (struct df_byte_lr_problem_data *)df_byte_lr->problem_data; - bitmap op1 = &df_byte_lr_get_bb_info (bb->index)->out; - if (bb != EXIT_BLOCK_PTR) - bitmap_copy (op1, &problem_data->hardware_regs_used); -} - - /* Confluence function that ignores fake edges. */ static bool -df_byte_lr_confluence_n (edge e) +df_word_lr_confluence_n (edge e) { - struct df_byte_lr_problem_data *problem_data - = (struct df_byte_lr_problem_data *)df_byte_lr->problem_data; - bitmap op1 = &df_byte_lr_get_bb_info (e->src->index)->out; - bitmap op2 = &df_byte_lr_get_bb_info (e->dest->index)->in; - bool changed = false; + bitmap op1 = &df_word_lr_get_bb_info (e->src->index)->out; + bitmap op2 = &df_word_lr_get_bb_info (e->dest->index)->in; - /* Call-clobbered registers die across exception and call edges. */ - /* ??? Abnormal call edges ignored for the moment, as this gets - confused by sibling call edges, which crashes reg-stack. */ - if (e->flags & EDGE_EH) - changed = bitmap_ior_and_compl_into (op1, op2, - &problem_data->invalidated_by_call); - else - changed = bitmap_ior_into (op1, op2); - - changed |= bitmap_ior_into (op1, &problem_data->hardware_regs_used); - return changed; + return bitmap_ior_into (op1, op2); } /* Transfer function. */ static bool -df_byte_lr_transfer_function (int bb_index) +df_word_lr_transfer_function (int bb_index) { - struct df_byte_lr_bb_info *bb_info = df_byte_lr_get_bb_info (bb_index); + struct df_word_lr_bb_info *bb_info = df_word_lr_get_bb_info (bb_index); bitmap in = &bb_info->in; bitmap out = &bb_info->out; bitmap use = &bb_info->use; @@ -2755,86 +2567,83 @@ df_byte_lr_transfer_function (int bb_index) /* Free all storage associated with the problem. */ static void -df_byte_lr_free (void) +df_word_lr_free (void) { - struct df_byte_lr_problem_data *problem_data - = (struct df_byte_lr_problem_data *)df_byte_lr->problem_data; + struct df_word_lr_problem_data *problem_data + = (struct df_word_lr_problem_data *)df_word_lr->problem_data; - - if (df_byte_lr->block_info) + if (df_word_lr->block_info) { - df_byte_lr->block_info_size = 0; - free (df_byte_lr->block_info); - df_byte_lr->block_info = NULL; + df_word_lr->block_info_size = 0; + free (df_word_lr->block_info); + df_word_lr->block_info = NULL; } - BITMAP_FREE (df_byte_lr->out_of_date_transfer_functions); - bitmap_obstack_release (&problem_data->byte_lr_bitmaps); - free (problem_data->regno_start); - free (problem_data->regno_len); + BITMAP_FREE (df_word_lr->out_of_date_transfer_functions); + bitmap_obstack_release (&problem_data->word_lr_bitmaps); free (problem_data); - free (df_byte_lr); + free (df_word_lr); } /* Debugging info at top of bb. */ static void -df_byte_lr_top_dump (basic_block bb, FILE *file) +df_word_lr_top_dump (basic_block bb, FILE *file) { - struct df_byte_lr_bb_info *bb_info = df_byte_lr_get_bb_info (bb->index); + struct df_word_lr_bb_info *bb_info = df_word_lr_get_bb_info (bb->index); if (!bb_info) return; fprintf (file, ";; blr in \t"); - df_print_byte_regset (file, &bb_info->in); + df_print_word_regset (file, &bb_info->in); fprintf (file, ";; blr use \t"); - df_print_byte_regset (file, &bb_info->use); + df_print_word_regset (file, &bb_info->use); fprintf (file, ";; blr def \t"); - df_print_byte_regset (file, &bb_info->def); + df_print_word_regset (file, &bb_info->def); } /* Debugging info at bottom of bb. */ static void -df_byte_lr_bottom_dump (basic_block bb, FILE *file) +df_word_lr_bottom_dump (basic_block bb, FILE *file) { - struct df_byte_lr_bb_info *bb_info = df_byte_lr_get_bb_info (bb->index); + struct df_word_lr_bb_info *bb_info = df_word_lr_get_bb_info (bb->index); if (!bb_info) return; fprintf (file, ";; blr out \t"); - df_print_byte_regset (file, &bb_info->out); + df_print_word_regset (file, &bb_info->out); } /* All of the information associated with every instance of the problem. */ -static struct df_problem problem_BYTE_LR = +static struct df_problem problem_WORD_LR = { - DF_BYTE_LR, /* Problem id. */ + DF_WORD_LR, /* Problem id. */ DF_BACKWARD, /* Direction. */ - df_byte_lr_alloc, /* Allocate the problem specific data. */ - df_byte_lr_reset, /* Reset global information. */ - df_byte_lr_free_bb_info, /* Free basic block info. */ - df_byte_lr_local_compute, /* Local compute function. */ - df_byte_lr_init, /* Init the solution specific data. */ + df_word_lr_alloc, /* Allocate the problem specific data. */ + df_word_lr_reset, /* Reset global information. */ + df_word_lr_free_bb_info, /* Free basic block info. */ + df_word_lr_local_compute, /* Local compute function. */ + df_word_lr_init, /* Init the solution specific data. */ df_worklist_dataflow, /* Worklist solver. */ - df_byte_lr_confluence_0, /* Confluence operator 0. */ - df_byte_lr_confluence_n, /* Confluence operator n. */ - df_byte_lr_transfer_function, /* Transfer function. */ + NULL, /* Confluence operator 0. */ + df_word_lr_confluence_n, /* Confluence operator n. */ + df_word_lr_transfer_function, /* Transfer function. */ NULL, /* Finalize function. */ - df_byte_lr_free, /* Free all of the problem information. */ - df_byte_lr_free, /* Remove this problem from the stack of dataflow problems. */ + df_word_lr_free, /* Free all of the problem information. */ + df_word_lr_free, /* Remove this problem from the stack of dataflow problems. */ NULL, /* Debugging. */ - df_byte_lr_top_dump, /* Debugging start block. */ - df_byte_lr_bottom_dump, /* Debugging end block. */ + df_word_lr_top_dump, /* Debugging start block. */ + df_word_lr_bottom_dump, /* Debugging end block. */ NULL, /* Incremental solution verify start. */ NULL, /* Incremental solution verify end. */ NULL, /* Dependent problem. */ - sizeof (struct df_byte_lr_bb_info),/* Size of entry of block_info array. */ - TV_DF_BYTE_LR, /* Timing variable. */ + sizeof (struct df_word_lr_bb_info),/* Size of entry of block_info array. */ + TV_DF_WORD_LR, /* Timing variable. */ false /* Reset blocks on dropping out of blocks_to_analyze. */ }; @@ -2844,163 +2653,50 @@ static struct df_problem problem_BYTE_LR = solution. */ void -df_byte_lr_add_problem (void) +df_word_lr_add_problem (void) { - df_add_problem (&problem_BYTE_LR); + df_add_problem (&problem_WORD_LR); /* These will be initialized when df_scan_blocks processes each block. */ - df_byte_lr->out_of_date_transfer_functions = BITMAP_ALLOC (NULL); + df_word_lr->out_of_date_transfer_functions = BITMAP_ALLOC (NULL); } -/* Simulate the effects of the defs of INSN on LIVE. */ +/* Simulate the effects of the defs of INSN on LIVE. Return true if we changed + any bits, which is used by the caller to determine whether a set is + necessary. We also return true if there are other reasons not to delete + an insn. */ -void -df_byte_lr_simulate_defs (rtx insn, bitmap live) +bool +df_word_lr_simulate_defs (rtx insn, bitmap live) { - struct df_byte_lr_problem_data *problem_data - = (struct df_byte_lr_problem_data *)df_byte_lr->problem_data; + bool changed = false; df_ref *def_rec; unsigned int uid = INSN_UID (insn); for (def_rec = DF_INSN_UID_DEFS (uid); *def_rec; def_rec++) { df_ref def = *def_rec; - - /* If the def is to only part of the reg, it does - not kill the other defs that reach here. */ - if (!(DF_REF_FLAGS (def) & DF_REF_CONDITIONAL)) - { - unsigned int dregno = DF_REF_REGNO (def); - unsigned int start = problem_data->regno_start[dregno]; - unsigned int len = problem_data->regno_len[dregno]; - unsigned int sb; - unsigned int lb; - if (!df_compute_accessed_bytes (def, DF_MM_MUST, &sb, &lb)) - { - start += sb; - len = lb - sb; - } - - if (len) - bitmap_clear_range (live, start, len); - } + if (DF_REF_FLAGS (def) & DF_REF_CONDITIONAL) + changed = true; + else + changed |= df_word_lr_mark_ref (*def_rec, false, live); } + return changed; } /* Simulate the effects of the uses of INSN on LIVE. */ void -df_byte_lr_simulate_uses (rtx insn, bitmap live) +df_word_lr_simulate_uses (rtx insn, bitmap live) { - struct df_byte_lr_problem_data *problem_data - = (struct df_byte_lr_problem_data *)df_byte_lr->problem_data; df_ref *use_rec; unsigned int uid = INSN_UID (insn); for (use_rec = DF_INSN_UID_USES (uid); *use_rec; use_rec++) - { - df_ref use = *use_rec; - unsigned int uregno = DF_REF_REGNO (use); - unsigned int start = problem_data->regno_start[uregno]; - unsigned int len = problem_data->regno_len[uregno]; - unsigned int sb; - unsigned int lb; - - if (!df_compute_accessed_bytes (use, DF_MM_MAY, &sb, &lb)) - { - start += sb; - len = lb - sb; - } - - /* Add use to set of uses in this BB. */ - if (len) - bitmap_set_range (live, start, len); - } + df_word_lr_mark_ref (*use_rec, true, live); } - - -/* Apply the artificial uses and defs at the top of BB in a forwards - direction. */ - -void -df_byte_lr_simulate_artificial_refs_at_top (basic_block bb, bitmap live) -{ - struct df_byte_lr_problem_data *problem_data - = (struct df_byte_lr_problem_data *)df_byte_lr->problem_data; - df_ref *def_rec; -#ifdef EH_USES - df_ref *use_rec; -#endif - int bb_index = bb->index; - -#ifdef EH_USES - for (use_rec = df_get_artificial_uses (bb_index); *use_rec; use_rec++) - { - df_ref use = *use_rec; - if (DF_REF_FLAGS (use) & DF_REF_AT_TOP) - { - unsigned int uregno = DF_REF_REGNO (use); - unsigned int start = problem_data->regno_start[uregno]; - unsigned int len = problem_data->regno_len[uregno]; - bitmap_set_range (live, start, len); - } - } -#endif - - for (def_rec = df_get_artificial_defs (bb_index); *def_rec; def_rec++) - { - df_ref def = *def_rec; - if (DF_REF_FLAGS (def) & DF_REF_AT_TOP) - { - unsigned int dregno = DF_REF_REGNO (def); - unsigned int start = problem_data->regno_start[dregno]; - unsigned int len = problem_data->regno_len[dregno]; - bitmap_clear_range (live, start, len); - } - } -} - - -/* Apply the artificial uses and defs at the end of BB in a backwards - direction. */ - -void -df_byte_lr_simulate_artificial_refs_at_end (basic_block bb, bitmap live) -{ - struct df_byte_lr_problem_data *problem_data - = (struct df_byte_lr_problem_data *)df_byte_lr->problem_data; - df_ref *def_rec; - df_ref *use_rec; - int bb_index = bb->index; - - for (def_rec = df_get_artificial_defs (bb_index); *def_rec; def_rec++) - { - df_ref def = *def_rec; - if ((DF_REF_FLAGS (def) & DF_REF_AT_TOP) == 0) - { - unsigned int dregno = DF_REF_REGNO (def); - unsigned int start = problem_data->regno_start[dregno]; - unsigned int len = problem_data->regno_len[dregno]; - bitmap_clear_range (live, start, len); - } - } - - for (use_rec = df_get_artificial_uses (bb_index); *use_rec; use_rec++) - { - df_ref use = *use_rec; - if ((DF_REF_FLAGS (use) & DF_REF_AT_TOP) == 0) - { - unsigned int uregno = DF_REF_REGNO (use); - unsigned int start = problem_data->regno_start[uregno]; - unsigned int len = problem_data->regno_len[uregno]; - bitmap_set_range (live, start, len); - } - } -} - - /*---------------------------------------------------------------------------- This problem computes REG_DEAD and REG_UNUSED notes. diff --git a/gcc/df.h b/gcc/df.h index 01a4d1046e9..a585b3bf744 100644 --- a/gcc/df.h +++ b/gcc/df.h @@ -52,7 +52,7 @@ union df_ref_d; #define DF_LIVE 2 /* Live Registers & Uninitialized Registers */ #define DF_RD 3 /* Reaching Defs. */ #define DF_CHAIN 4 /* Def-Use and/or Use-Def Chains. */ -#define DF_BYTE_LR 5 /* Subreg tracking lr. */ +#define DF_WORD_LR 5 /* Subreg tracking lr. */ #define DF_NOTE 6 /* REG_DEF and REG_UNUSED notes. */ #define DF_MD 7 /* Multiple Definitions. */ @@ -66,14 +66,6 @@ enum df_flow_dir DF_BACKWARD }; -/* Used in the byte scanning to determine if may or must info is to be - returned. */ -enum df_mm - { - DF_MM_MAY, - DF_MM_MUST - }; - /* Descriminator for the various df_ref types. */ enum df_ref_class {DF_REF_BASE, DF_REF_ARTIFICIAL, DF_REF_REGULAR, DF_REF_EXTRACT}; @@ -624,7 +616,7 @@ struct df_d #define DF_RD_BB_INFO(BB) (df_rd_get_bb_info((BB)->index)) #define DF_LR_BB_INFO(BB) (df_lr_get_bb_info((BB)->index)) #define DF_LIVE_BB_INFO(BB) (df_live_get_bb_info((BB)->index)) -#define DF_BYTE_LR_BB_INFO(BB) (df_byte_lr_get_bb_info((BB)->index)) +#define DF_WORD_LR_BB_INFO(BB) (df_word_lr_get_bb_info((BB)->index)) #define DF_MD_BB_INFO(BB) (df_md_get_bb_info((BB)->index)) /* Most transformations that wish to use live register analysis will @@ -641,8 +633,8 @@ struct df_d /* These macros are used by passes that are not tolerant of uninitialized variables. This intolerance should eventually be fixed. */ -#define DF_BYTE_LR_IN(BB) (&DF_BYTE_LR_BB_INFO(BB)->in) -#define DF_BYTE_LR_OUT(BB) (&DF_BYTE_LR_BB_INFO(BB)->out) +#define DF_WORD_LR_IN(BB) (&DF_WORD_LR_BB_INFO(BB)->in) +#define DF_WORD_LR_OUT(BB) (&DF_WORD_LR_BB_INFO(BB)->out) /* Macros to access the elements within the ref structure. */ @@ -859,9 +851,11 @@ struct df_live_bb_info /* Live registers, a backwards dataflow problem. These bitmaps are -indexed by the df_byte_lr_offset array which is indexed by pseudo. */ + indexed by 2 * regno for each pseudo and have two entries for each + pseudo. Only pseudos that have a size of 2 * UNITS_PER_WORD are + meaningfully tracked. */ -struct df_byte_lr_bb_info +struct df_word_lr_bb_info { /* Local sets to describe the basic blocks. */ bitmap_head def; /* The set of registers set in this block @@ -883,7 +877,7 @@ extern struct df_d *df; #define df_lr (df->problems_by_index[DF_LR]) #define df_live (df->problems_by_index[DF_LIVE]) #define df_chain (df->problems_by_index[DF_CHAIN]) -#define df_byte_lr (df->problems_by_index[DF_BYTE_LR]) +#define df_word_lr (df->problems_by_index[DF_WORD_LR]) #define df_note (df->problems_by_index[DF_NOTE]) #define df_md (df->problems_by_index[DF_MD]) @@ -933,7 +927,7 @@ extern df_ref df_find_use (rtx, rtx); extern bool df_reg_used (rtx, rtx); extern void df_worklist_dataflow (struct dataflow *,bitmap, int *, int); extern void df_print_regset (FILE *file, bitmap r); -extern void df_print_byte_regset (FILE *file, bitmap r); +extern void df_print_word_regset (FILE *file, bitmap r); extern void df_dump (FILE *); extern void df_dump_region (FILE *); extern void df_dump_start (FILE *); @@ -972,13 +966,12 @@ extern void df_live_verify_transfer_functions (void); extern void df_live_add_problem (void); extern void df_live_set_all_dirty (void); extern void df_chain_add_problem (unsigned int); -extern void df_byte_lr_add_problem (void); -extern int df_byte_lr_get_regno_start (unsigned int); -extern int df_byte_lr_get_regno_len (unsigned int); -extern void df_byte_lr_simulate_defs (rtx, bitmap); -extern void df_byte_lr_simulate_uses (rtx, bitmap); -extern void df_byte_lr_simulate_artificial_refs_at_top (basic_block, bitmap); -extern void df_byte_lr_simulate_artificial_refs_at_end (basic_block, bitmap); +extern void df_word_lr_add_problem (void); +extern bool df_word_lr_mark_ref (df_ref, bool, bitmap); +extern bool df_word_lr_simulate_defs (rtx, bitmap); +extern void df_word_lr_simulate_uses (rtx, bitmap); +extern void df_word_lr_simulate_artificial_refs_at_top (basic_block, bitmap); +extern void df_word_lr_simulate_artificial_refs_at_end (basic_block, bitmap); extern void df_note_add_problem (void); extern void df_md_add_problem (void); extern void df_md_simulate_artificial_defs_at_top (basic_block, bitmap); @@ -1029,11 +1022,6 @@ extern void df_compute_regs_ever_live (bool); extern bool df_read_modify_subreg_p (rtx); extern void df_scan_verify (void); -/* Functions defined in df-byte-scan.c. */ -extern bool df_compute_accessed_bytes (df_ref, enum df_mm, - unsigned int *, unsigned int *); - - /* Get basic block info. */ static inline struct df_scan_bb_info * @@ -1081,11 +1069,11 @@ df_live_get_bb_info (unsigned int index) return NULL; } -static inline struct df_byte_lr_bb_info * -df_byte_lr_get_bb_info (unsigned int index) +static inline struct df_word_lr_bb_info * +df_word_lr_get_bb_info (unsigned int index) { - if (index < df_byte_lr->block_info_size) - return &((struct df_byte_lr_bb_info *) df_byte_lr->block_info)[index]; + if (index < df_word_lr->block_info_size) + return &((struct df_word_lr_bb_info *) df_word_lr->block_info)[index]; else return NULL; } diff --git a/gcc/lower-subreg.c b/gcc/lower-subreg.c index 1cc972ac72d..6876f0991ee 100644 --- a/gcc/lower-subreg.c +++ b/gcc/lower-subreg.c @@ -33,6 +33,7 @@ along with GCC; see the file COPYING3. If not see #include "basic-block.h" #include "recog.h" #include "bitmap.h" +#include "dce.h" #include "expr.h" #include "except.h" #include "regs.h" @@ -1091,6 +1092,9 @@ decompose_multiword_subregs (void) return; } + if (df) + run_word_dce (); + /* FIXME: When the dataflow branch is merged, we can change this code to look for each multi-word pseudo-register and to find each insn which sets or uses that register. That should be faster diff --git a/gcc/timevar.def b/gcc/timevar.def index a3e93bc4d06..b5e1d2372d1 100644 --- a/gcc/timevar.def +++ b/gcc/timevar.def @@ -91,7 +91,7 @@ DEFTIMEVAR (TV_DF_LR , "df live regs") DEFTIMEVAR (TV_DF_LIVE , "df live&initialized regs") DEFTIMEVAR (TV_DF_UREC , "df uninitialized regs 2") DEFTIMEVAR (TV_DF_CHAIN , "df use-def / def-use chains") -DEFTIMEVAR (TV_DF_BYTE_LR , "df live byte regs") +DEFTIMEVAR (TV_DF_WORD_LR , "df live reg subwords") DEFTIMEVAR (TV_DF_NOTE , "df reg dead/unused notes") DEFTIMEVAR (TV_REG_STATS , "register information")