re PR rtl-optimization/24762 ([killloop-branch] code motion of non-invariant expressions with hard registers.)
2006-01-27 Daniel Berlin <dberlin@dberlin.org> Kenneth Zadeck <zadeck@naturalbridge.com> PR rtl-optimization/24762 * doc/tm.texi: Added TARGET_EXTRA_LIVE_ON_ENTRY. * targhooks.c (hook_void_bitmap): New hook prototype. * targhoohs.h (hook_void_bitmap): Ditto. * bitmap.h (bitmap_head_def): Moved to coretypes.h. * coretypes.h (bitmap_head_def): Moved from bitmap.h. * target.h (live_on_entry): New function pointer. * df-scan.c (df_all_hard_regs): Removed. (df_scan_dump, df_hard_reg_init): Removed df_all_hard_regs. (df_scan_free_internal): Added df->entry_block_defs. (df_scan_alloc): Ditto. (df_scan_dump): Ditto. (df_uses_record): Plumbed flag field properly thru calls. Record EH_RETURN_DATA_REGNO in eh blocks unconditionally. This part fixes PR24762. (df_bb_refs_record): Added code to make the frame and arg pointers live in EH blocks. (df_refs_record): Added call to df_record_entry_block_defs. (df_record_entry_block_defs): New function. * df-core.c: Added comments to describe new artifical defs. * df.h (DF_REF_DIES_AFTER_THIS_USE): New flag in enum df_ref_flags. (entry_block_defs): New field in struct df. (df_all_hard_regs): Deleted. * target-def.h: Added TARGET_EXTRA_LIVE_ON_ENTRY. * df-problems.c (df_ru_bb_local_compute_process_def): Added code to handle artifical defs in the entry to a function. (df_ru_bb_local_compute): Ditto. (df_rd_bb_local_compute_process_def): Ditto. (df_rd_bb_local_compute): Ditto. (df_lr_bb_local_compute): Ditto. (df_ur_bb_local_compute): Ditto. (df_urec_bb_local_compute): Ditto. (df_chain_create_bb): Ditto. (df_ur_local_finalize): Removed entry. (df_urec_init): Ditto. (df_urec_local_finalize): Ditto. (df_ri_bb_compute): Added detection of last use of pseudos. * Makefile.in (df-scan.o): Updated dependencies. * config/mips/mips-protos.h (mips_set_live_on_entry): Added. * config/mips/mips.c (mips_set_live_on_entry): Added. * config/mips/mips.c (TARGET_EXTRA_LIVE_ON_ENTRY): Added value for target hook. * dce.c (marked_insn_p): Added code to handle artifical defs. Co-Authored-By: Kenneth Zadeck <zadeck@naturalbridge.com> From-SVN: r110312
This commit is contained in:
parent
7744bbe369
commit
912f2dacdf
@ -1,3 +1,50 @@
|
||||
2006-01-27 Daniel Berlin <dberlin@dberlin.org>
|
||||
Kenneth Zadeck <zadeck@naturalbridge.com>
|
||||
|
||||
PR rtl-optimization/24762
|
||||
* doc/tm.texi: Added TARGET_EXTRA_LIVE_ON_ENTRY.
|
||||
* targhooks.c (hook_void_bitmap): New hook prototype.
|
||||
* targhoohs.h (hook_void_bitmap): Ditto.
|
||||
* bitmap.h (bitmap_head_def): Moved to coretypes.h.
|
||||
* coretypes.h (bitmap_head_def): Moved from bitmap.h.
|
||||
* target.h (live_on_entry): New function pointer.
|
||||
* df-scan.c (df_all_hard_regs): Removed.
|
||||
(df_scan_dump, df_hard_reg_init): Removed df_all_hard_regs.
|
||||
(df_scan_free_internal): Added df->entry_block_defs.
|
||||
(df_scan_alloc): Ditto.
|
||||
(df_scan_dump): Ditto.
|
||||
(df_uses_record): Plumbed flag field properly thru calls.
|
||||
Record EH_RETURN_DATA_REGNO in eh blocks unconditionally.
|
||||
This part fixes PR24762.
|
||||
(df_bb_refs_record): Added code to make the frame and arg
|
||||
pointers live in EH blocks.
|
||||
(df_refs_record): Added call to df_record_entry_block_defs.
|
||||
(df_record_entry_block_defs): New function.
|
||||
* df-core.c: Added comments to describe new artifical defs.
|
||||
* df.h (DF_REF_DIES_AFTER_THIS_USE): New flag in enum df_ref_flags.
|
||||
(entry_block_defs): New field in struct df.
|
||||
(df_all_hard_regs): Deleted.
|
||||
* target-def.h: Added TARGET_EXTRA_LIVE_ON_ENTRY.
|
||||
* df-problems.c (df_ru_bb_local_compute_process_def):
|
||||
Added code to handle artifical defs in the entry to a function.
|
||||
(df_ru_bb_local_compute): Ditto.
|
||||
(df_rd_bb_local_compute_process_def): Ditto.
|
||||
(df_rd_bb_local_compute): Ditto.
|
||||
(df_lr_bb_local_compute): Ditto.
|
||||
(df_ur_bb_local_compute): Ditto.
|
||||
(df_urec_bb_local_compute): Ditto.
|
||||
(df_chain_create_bb): Ditto.
|
||||
(df_ur_local_finalize): Removed entry.
|
||||
(df_urec_init): Ditto.
|
||||
(df_urec_local_finalize): Ditto.
|
||||
(df_ri_bb_compute): Added detection of last use of pseudos.
|
||||
* Makefile.in (df-scan.o): Updated dependencies.
|
||||
* config/mips/mips-protos.h (mips_set_live_on_entry): Added.
|
||||
* config/mips/mips.c (mips_set_live_on_entry): Added.
|
||||
* config/mips/mips.c (TARGET_EXTRA_LIVE_ON_ENTRY): Added value
|
||||
for target hook.
|
||||
* dce.c (marked_insn_p): Added code to handle artifical defs.
|
||||
|
||||
2006-01-27 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
* config/i386/emmintrin.h (_mm_cvtsd_f64): Add missing Intel
|
||||
|
@ -2337,9 +2337,9 @@ df-problems.o : df-problems.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
|
||||
hard-reg-set.h $(BASIC_BLOCK_H) $(DF_H) bitmap.h sbitmap.h $(TM_P_H) \
|
||||
$(FLAGS_H) output.h
|
||||
df-scan.o : df-scan.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
|
||||
insn-config.h $(RECOG_H) $(FUNCTION_H) $(REGS_H) alloc-pool.h hard-reg-set.h \
|
||||
$(BASIC_BLOCK_H) $(DF_H) bitmap.h sbitmap.h $(TM_P_H) $(FLAGS_H) \
|
||||
output.h
|
||||
insn-config.h $(RECOG_H) $(FUNCTION_H) $(REGS_H) alloc-pool.h \
|
||||
hard-reg-set.h $(BASIC_BLOCK_H) $(DF_H) bitmap.h sbitmap.h $(TM_P_H) \
|
||||
$(FLAGS_H) $(TARGET_H) $(TARGET_DEF_H) $(TREE_H) output.h tree-pass.h
|
||||
var-tracking.o : var-tracking.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
|
||||
$(RTL_H) $(TREE_H) hard-reg-set.h insn-config.h reload.h $(FLAGS_H) \
|
||||
$(BASIC_BLOCK_H) output.h sbitmap.h alloc-pool.h $(FIBHEAP_H) $(HASHTAB_H) \
|
||||
|
@ -77,8 +77,6 @@ typedef struct bitmap_head_def GTY(()) {
|
||||
} bitmap_head;
|
||||
|
||||
|
||||
typedef struct bitmap_head_def *bitmap;
|
||||
|
||||
/* Global data */
|
||||
extern bitmap_element bitmap_zero_bits; /* Zero bitmap element */
|
||||
extern bitmap_obstack bitmap_default_obstack; /* Default bitmap obstack */
|
||||
|
@ -119,6 +119,7 @@ extern bool mips_legitimate_address_p (enum machine_mode, rtx, int);
|
||||
extern rtx mips_unspec_address (rtx, enum mips_symbol_type);
|
||||
extern bool mips_legitimize_address (rtx *, enum machine_mode);
|
||||
extern bool mips_legitimize_move (enum machine_mode, rtx, rtx);
|
||||
extern void mips_set_live_on_entry (void *);
|
||||
|
||||
extern int m16_uimm3_b (rtx, enum machine_mode);
|
||||
extern int m16_simm4_1 (rtx, enum machine_mode);
|
||||
|
@ -56,6 +56,7 @@ Boston, MA 02110-1301, USA. */
|
||||
#include "cfglayout.h"
|
||||
#include "sched-int.h"
|
||||
#include "tree-gimple.h"
|
||||
#include "bitmap.h"
|
||||
|
||||
/* True if X is an unspec wrapper around a SYMBOL_REF or LABEL_REF. */
|
||||
#define UNSPEC_ADDRESS_P(X) \
|
||||
@ -407,6 +408,7 @@ static rtx mips_expand_builtin_compare (enum mips_builtin_type,
|
||||
rtx, tree);
|
||||
static rtx mips_expand_builtin_bposge (enum mips_builtin_type, rtx);
|
||||
static void mips_encode_section_info (tree, rtx, int);
|
||||
static void mips_extra_live_on_entry (bitmap);
|
||||
|
||||
/* Structure to be filled in by compute_frame_size with register
|
||||
save masks, and offsets for the current function. */
|
||||
@ -1160,6 +1162,12 @@ static struct mips_rtx_cost_data const mips_rtx_cost_data[PROCESSOR_MAX] =
|
||||
#undef TARGET_ATTRIBUTE_TABLE
|
||||
#define TARGET_ATTRIBUTE_TABLE mips_attribute_table
|
||||
|
||||
#undef TARGET_EXTRA_LIVE_ON_ENTRY
|
||||
/* With -mabicalls (which is the default on GNU/Linux),
|
||||
PIC_FUNCTION_ADDR_REGNUM is live on function entry and is to
|
||||
initialize $28, which is PIC_OFFSET_TABLE_REGNUM. */
|
||||
#define TARGET_EXTRA_LIVE_ON_ENTRY mips_extra_live_on_entry
|
||||
|
||||
struct gcc_target targetm = TARGET_INITIALIZER;
|
||||
|
||||
/* Classify symbol X, which must be a SYMBOL_REF or a LABEL_REF. */
|
||||
@ -10764,5 +10772,16 @@ mips_encode_section_info (tree decl, rtx rtl, int first)
|
||||
SYMBOL_REF_FLAGS (symbol) |= SYMBOL_FLAG_LONG_CALL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Implement TARGET_EXTRA_LIVE_ON_ENTRY. TARGET_ABICALLS makes
|
||||
PIC_FUNCTION_ADDR_REGNUM live on entry to a function. */
|
||||
|
||||
static void
|
||||
mips_extra_live_on_entry (bitmap regs)
|
||||
{
|
||||
if (!TARGET_ABICALLS)
|
||||
bitmap_set_bit (regs, PIC_FUNCTION_ADDR_REGNUM);
|
||||
}
|
||||
|
||||
|
||||
#include "gt-mips.h"
|
||||
|
@ -37,6 +37,8 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
|
||||
#ifndef USED_FOR_TARGET
|
||||
|
||||
struct bitmap_head_def;
|
||||
typedef struct bitmap_head_def *bitmap;
|
||||
struct rtx_def;
|
||||
typedef struct rtx_def *rtx;
|
||||
struct rtvec_def;
|
||||
|
@ -205,18 +205,23 @@ There are 4 ways to obtain access to refs:
|
||||
defs and uses are only there if DF_HARD_REGS was specified when the
|
||||
df instance was created.
|
||||
|
||||
Artificial defs and uses occur at the beginning blocks that are the
|
||||
destination of eh edges. The defs come from the registers
|
||||
specified in EH_RETURN_DATA_REGNO and the uses come from the
|
||||
registers specified in ED_USES. Logically these defs and uses
|
||||
should really occur along the eh edge, but there is no convienent
|
||||
way to do this. Artificial edges that occur at the beginning of
|
||||
the block have the DF_REF_AT_TOP flag set.
|
||||
|
||||
Artificial uses also occur at the end of all blocks. These arise
|
||||
from the hard registers that are always live, such as the stack
|
||||
register and are put there to keep the code from forgetting about
|
||||
them.
|
||||
Artificial defs and uses occur both at the beginning and ends of blocks.
|
||||
|
||||
For blocks that area at the destination of eh edges, the
|
||||
artificial uses and defs occur at the beginning. The defs relate
|
||||
to the registers specified in EH_RETURN_DATA_REGNO and the uses
|
||||
relate to the registers specified in ED_USES. Logically these
|
||||
defs and uses should really occur along the eh edge, but there is
|
||||
no convenient way to do this. Artificial edges that occur at the
|
||||
beginning of the block have the DF_REF_AT_TOP flag set.
|
||||
|
||||
Artificial uses occur at the end of all blocks. These arise from
|
||||
the hard registers that are always live, such as the stack
|
||||
register and are put there to keep the code from forgetting about
|
||||
them.
|
||||
|
||||
Artifical defs occur at the end of the entry block. These arise
|
||||
from registers that are live at entry to the function.
|
||||
|
||||
2) All of the uses and defs associated with each pseudo or hard
|
||||
register are linked in a bidirectional chain. These are called
|
||||
|
@ -298,7 +298,7 @@ struct df_ru_problem_data
|
||||
unsigned int use_sites_size; /* Size of use_sites. */
|
||||
/* The set of defs to regs invalidated by call. */
|
||||
bitmap sparse_invalidated_by_call;
|
||||
/* The set of defs to regs invalidate by call for ru. */
|
||||
/* The set of defs to regs invalidated by call for ru. */
|
||||
bitmap dense_invalidated_by_call;
|
||||
};
|
||||
|
||||
@ -429,37 +429,41 @@ df_ru_alloc (struct dataflow *dflow, bitmap blocks_to_rescan)
|
||||
static void
|
||||
df_ru_bb_local_compute_process_def (struct dataflow *dflow,
|
||||
struct df_ru_bb_info *bb_info,
|
||||
struct df_ref *def)
|
||||
struct df_ref *def,
|
||||
enum df_ref_flags top_flag)
|
||||
{
|
||||
struct df *df = dflow->df;
|
||||
while (def)
|
||||
{
|
||||
unsigned int regno = DF_REF_REGNO (def);
|
||||
unsigned int begin = DF_REG_USE_GET (df, regno)->begin;
|
||||
unsigned int n_uses = DF_REG_USE_GET (df, regno)->n_refs;
|
||||
if (!bitmap_bit_p (seen_in_block, regno))
|
||||
if (top_flag == (DF_REF_FLAGS (def) & DF_REF_AT_TOP))
|
||||
{
|
||||
/* The first def for regno, causes the kill info to be
|
||||
generated and the gen information to cleared. */
|
||||
if (!bitmap_bit_p (seen_in_insn, regno))
|
||||
unsigned int regno = DF_REF_REGNO (def);
|
||||
unsigned int begin = DF_REG_USE_GET (df, regno)->begin;
|
||||
unsigned int n_uses = DF_REG_USE_GET (df, regno)->n_refs;
|
||||
if (!bitmap_bit_p (seen_in_block, regno))
|
||||
{
|
||||
if (n_uses > DF_SPARSE_THRESHOLD)
|
||||
/* The first def for regno, causes the kill info to be
|
||||
generated and the gen information to cleared. */
|
||||
if (!bitmap_bit_p (seen_in_insn, regno))
|
||||
{
|
||||
bitmap_set_bit (bb_info->sparse_kill, regno);
|
||||
bitmap_clear_range (bb_info->gen, begin, n_uses);
|
||||
}
|
||||
else
|
||||
{
|
||||
struct df_ru_problem_data *problem_data =
|
||||
(struct df_ru_problem_data *) dflow->problem_data;
|
||||
bitmap uses =
|
||||
df_ref_bitmap (problem_data->use_sites, regno,
|
||||
begin, n_uses);
|
||||
bitmap_ior_into (bb_info->kill, uses);
|
||||
bitmap_and_compl_into (bb_info->gen, uses);
|
||||
if (n_uses > DF_SPARSE_THRESHOLD)
|
||||
{
|
||||
bitmap_set_bit (bb_info->sparse_kill, regno);
|
||||
bitmap_clear_range (bb_info->gen, begin, n_uses);
|
||||
}
|
||||
else
|
||||
{
|
||||
struct df_ru_problem_data * problem_data =
|
||||
(struct df_ru_problem_data *)dflow->problem_data;
|
||||
bitmap uses =
|
||||
df_ref_bitmap (problem_data->use_sites, regno,
|
||||
begin, n_uses);
|
||||
bitmap_ior_into (bb_info->kill, uses);
|
||||
bitmap_and_compl_into (bb_info->gen, uses);
|
||||
}
|
||||
}
|
||||
bitmap_set_bit (seen_in_insn, regno);
|
||||
}
|
||||
bitmap_set_bit (seen_in_insn, regno);
|
||||
}
|
||||
def = def->next_ref;
|
||||
}
|
||||
@ -508,11 +512,9 @@ df_ru_bb_local_compute (struct dataflow *dflow, unsigned int bb_index)
|
||||
df_get_artificial_uses (df, bb_index),
|
||||
DF_REF_AT_TOP);
|
||||
#endif
|
||||
|
||||
/* Process the artificial defs first since these are at the top of
|
||||
the block. */
|
||||
df_ru_bb_local_compute_process_def (dflow, bb_info,
|
||||
df_get_artificial_defs (df, bb_index));
|
||||
df_get_artificial_defs (df, bb_index),
|
||||
DF_REF_AT_TOP);
|
||||
|
||||
FOR_BB_INSNS (bb, insn)
|
||||
{
|
||||
@ -521,7 +523,7 @@ df_ru_bb_local_compute (struct dataflow *dflow, unsigned int bb_index)
|
||||
continue;
|
||||
|
||||
df_ru_bb_local_compute_process_def (dflow, bb_info,
|
||||
DF_INSN_UID_GET (df, uid)->defs);
|
||||
DF_INSN_UID_GET (df, uid)->defs, 0);
|
||||
|
||||
/* The use processing must happen after the defs processing even
|
||||
though the uses logically happen first since the defs clear
|
||||
@ -537,6 +539,9 @@ df_ru_bb_local_compute (struct dataflow *dflow, unsigned int bb_index)
|
||||
/* Process the hardware registers that are always live. */
|
||||
df_ru_bb_local_compute_process_use (bb_info,
|
||||
df_get_artificial_uses (df, bb_index), 0);
|
||||
|
||||
df_ru_bb_local_compute_process_def (dflow, bb_info,
|
||||
df_get_artificial_defs (df, bb_index), 0);
|
||||
}
|
||||
|
||||
|
||||
@ -948,45 +953,49 @@ df_rd_alloc (struct dataflow *dflow, bitmap blocks_to_rescan)
|
||||
static void
|
||||
df_rd_bb_local_compute_process_def (struct dataflow *dflow,
|
||||
struct df_rd_bb_info *bb_info,
|
||||
struct df_ref *def)
|
||||
struct df_ref *def,
|
||||
enum df_ref_flags top_flag)
|
||||
{
|
||||
struct df *df = dflow->df;
|
||||
while (def)
|
||||
{
|
||||
unsigned int regno = DF_REF_REGNO (def);
|
||||
unsigned int begin = DF_REG_DEF_GET (df, regno)->begin;
|
||||
unsigned int n_defs = DF_REG_DEF_GET (df, regno)->n_refs;
|
||||
|
||||
/* Only the last def(s) for a regno in the block has any
|
||||
effect. */
|
||||
if (!bitmap_bit_p (seen_in_block, regno))
|
||||
if (top_flag == (DF_REF_FLAGS (def) & DF_REF_AT_TOP))
|
||||
{
|
||||
/* The first def for regno in insn gets to knock out the
|
||||
defs from other instructions. */
|
||||
if (!bitmap_bit_p (seen_in_insn, regno))
|
||||
{
|
||||
if (n_defs > DF_SPARSE_THRESHOLD)
|
||||
{
|
||||
bitmap_set_bit (bb_info->sparse_kill, regno);
|
||||
bitmap_clear_range (bb_info->gen, begin, n_defs);
|
||||
}
|
||||
else
|
||||
{
|
||||
struct df_rd_problem_data *problem_data =
|
||||
(struct df_rd_problem_data *) dflow->problem_data;
|
||||
bitmap defs =
|
||||
df_ref_bitmap (problem_data->def_sites, regno,
|
||||
begin, n_defs);
|
||||
bitmap_ior_into (bb_info->kill, defs);
|
||||
bitmap_and_compl_into (bb_info->gen, defs);
|
||||
}
|
||||
}
|
||||
unsigned int regno = DF_REF_REGNO (def);
|
||||
unsigned int begin = DF_REG_DEF_GET (df, regno)->begin;
|
||||
unsigned int n_defs = DF_REG_DEF_GET (df, regno)->n_refs;
|
||||
|
||||
bitmap_set_bit (seen_in_insn, regno);
|
||||
/* All defs for regno in the instruction may be put into
|
||||
the gen set. */
|
||||
if (! (DF_REF_FLAGS (def) & DF_REF_CLOBBER))
|
||||
bitmap_set_bit (bb_info->gen, DF_REF_ID (def));
|
||||
/* Only the last def(s) for a regno in the block has any
|
||||
effect. */
|
||||
if (!bitmap_bit_p (seen_in_block, regno))
|
||||
{
|
||||
/* The first def for regno in insn gets to knock out the
|
||||
defs from other instructions. */
|
||||
if (!bitmap_bit_p (seen_in_insn, regno))
|
||||
{
|
||||
if (n_defs > DF_SPARSE_THRESHOLD)
|
||||
{
|
||||
bitmap_set_bit (bb_info->sparse_kill, regno);
|
||||
bitmap_clear_range(bb_info->gen, begin, n_defs);
|
||||
}
|
||||
else
|
||||
{
|
||||
struct df_rd_problem_data * problem_data =
|
||||
(struct df_rd_problem_data *)dflow->problem_data;
|
||||
bitmap defs =
|
||||
df_ref_bitmap (problem_data->def_sites, regno,
|
||||
begin, n_defs);
|
||||
bitmap_ior_into (bb_info->kill, defs);
|
||||
bitmap_and_compl_into (bb_info->gen, defs);
|
||||
}
|
||||
}
|
||||
|
||||
bitmap_set_bit (seen_in_insn, regno);
|
||||
/* All defs for regno in the instruction may be put into
|
||||
the gen set. */
|
||||
if (! (DF_REF_FLAGS (def) & DF_REF_CLOBBER))
|
||||
bitmap_set_bit (bb_info->gen, DF_REF_ID (def));
|
||||
}
|
||||
}
|
||||
def = def->next_ref;
|
||||
}
|
||||
@ -1005,6 +1014,9 @@ df_rd_bb_local_compute (struct dataflow *dflow, unsigned int bb_index)
|
||||
bitmap_clear (seen_in_block);
|
||||
bitmap_clear (seen_in_insn);
|
||||
|
||||
df_rd_bb_local_compute_process_def (dflow, bb_info,
|
||||
df_get_artificial_defs (df, bb_index), 0);
|
||||
|
||||
FOR_BB_INSNS_REVERSE (bb, insn)
|
||||
{
|
||||
unsigned int uid = INSN_UID (insn);
|
||||
@ -1013,7 +1025,7 @@ df_rd_bb_local_compute (struct dataflow *dflow, unsigned int bb_index)
|
||||
continue;
|
||||
|
||||
df_rd_bb_local_compute_process_def (dflow, bb_info,
|
||||
DF_INSN_UID_GET (df, uid)->defs);
|
||||
DF_INSN_UID_GET (df, uid)->defs, 0);
|
||||
|
||||
/* This complex dance with the two bitmaps is required because
|
||||
instructions can assign twice to the same pseudo. This
|
||||
@ -1025,10 +1037,12 @@ df_rd_bb_local_compute (struct dataflow *dflow, unsigned int bb_index)
|
||||
bitmap_clear (seen_in_insn);
|
||||
}
|
||||
|
||||
/* Process the artificial defs last since we are going backwards
|
||||
thur the block and these are logically at the start. */
|
||||
/* Process the artificial defs at the top of the block last since we
|
||||
are going backwards through the block and these are logically at
|
||||
the start. */
|
||||
df_rd_bb_local_compute_process_def (dflow, bb_info,
|
||||
df_get_artificial_defs (df, bb_index));
|
||||
df_get_artificial_defs (df, bb_index),
|
||||
DF_REF_AT_TOP);
|
||||
}
|
||||
|
||||
|
||||
@ -1395,6 +1409,15 @@ df_lr_bb_local_compute (struct dataflow *dflow,
|
||||
struct df_ref *def;
|
||||
struct df_ref *use;
|
||||
|
||||
/* Process the registers set in an exception handler. */
|
||||
for (def = df_get_artificial_defs (df, bb_index); def; def = def->next_ref)
|
||||
if ((DF_REF_FLAGS (def) & DF_REF_AT_TOP) == 0)
|
||||
{
|
||||
unsigned int dregno = DF_REF_REGNO (def);
|
||||
bitmap_set_bit (bb_info->def, dregno);
|
||||
bitmap_clear_bit (bb_info->use, dregno);
|
||||
}
|
||||
|
||||
/* Process the hardware registers that are always live. */
|
||||
for (use = df_get_artificial_uses (df, bb_index); use; use = use->next_ref)
|
||||
/* Add use to set of uses in this BB. */
|
||||
@ -1455,12 +1478,13 @@ df_lr_bb_local_compute (struct dataflow *dflow,
|
||||
|
||||
/* Process the registers set in an exception handler. */
|
||||
for (def = df_get_artificial_defs (df, bb_index); def; def = def->next_ref)
|
||||
{
|
||||
unsigned int dregno = DF_REF_REGNO (def);
|
||||
bitmap_set_bit (bb_info->def, dregno);
|
||||
bitmap_clear_bit (bb_info->use, dregno);
|
||||
}
|
||||
|
||||
if (DF_REF_FLAGS (def) & DF_REF_AT_TOP)
|
||||
{
|
||||
unsigned int dregno = DF_REF_REGNO (def);
|
||||
bitmap_set_bit (bb_info->def, dregno);
|
||||
bitmap_clear_bit (bb_info->use, dregno);
|
||||
}
|
||||
|
||||
#ifdef EH_USES
|
||||
/* Process the uses that are live into an exception handler. */
|
||||
for (use = df_get_artificial_uses (df, bb_index); use; use = use->next_ref)
|
||||
@ -1783,6 +1807,17 @@ df_ur_bb_local_compute (struct dataflow *dflow, unsigned int bb_index)
|
||||
bitmap_clear (seen_in_block);
|
||||
bitmap_clear (seen_in_insn);
|
||||
|
||||
for (def = df_get_artificial_defs (df, bb_index); def; def = def->next_ref)
|
||||
if ((DF_REF_FLAGS (def) & DF_REF_AT_TOP) == 0)
|
||||
{
|
||||
unsigned int regno = DF_REF_REGNO (def);
|
||||
if (!bitmap_bit_p (seen_in_block, regno))
|
||||
{
|
||||
bitmap_set_bit (seen_in_block, regno);
|
||||
bitmap_set_bit (bb_info->gen, regno);
|
||||
}
|
||||
}
|
||||
|
||||
FOR_BB_INSNS_REVERSE (bb, insn)
|
||||
{
|
||||
unsigned int uid = INSN_UID (insn);
|
||||
@ -1808,14 +1843,15 @@ df_ur_bb_local_compute (struct dataflow *dflow, unsigned int bb_index)
|
||||
}
|
||||
|
||||
for (def = df_get_artificial_defs (df, bb_index); def; def = def->next_ref)
|
||||
{
|
||||
unsigned int regno = DF_REF_REGNO (def);
|
||||
if (!bitmap_bit_p (seen_in_block, regno))
|
||||
{
|
||||
bitmap_set_bit (seen_in_block, regno);
|
||||
bitmap_set_bit (bb_info->gen, regno);
|
||||
}
|
||||
}
|
||||
if (DF_REF_FLAGS (def) & DF_REF_AT_TOP)
|
||||
{
|
||||
unsigned int regno = DF_REF_REGNO (def);
|
||||
if (!bitmap_bit_p (seen_in_block, regno))
|
||||
{
|
||||
bitmap_set_bit (seen_in_block, regno);
|
||||
bitmap_set_bit (bb_info->gen, regno);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1875,9 +1911,6 @@ df_ur_local_finalize (struct dataflow *dflow, bitmap all_blocks)
|
||||
struct df_ur_bb_info *bb_info = df_ur_get_bb_info (dflow, bb_index);
|
||||
struct df_lr_bb_info *bb_lr_info = df_lr_get_bb_info (lr_dflow, bb_index);
|
||||
|
||||
bitmap_ior_into (bb_info->in, df_all_hard_regs);
|
||||
bitmap_ior_into (bb_info->out, df_all_hard_regs);
|
||||
|
||||
/* No register may reach a location where it is not used. Thus
|
||||
we trim the rr result to the places where it is used. */
|
||||
bitmap_and_into (bb_info->in, bb_lr_info->in);
|
||||
@ -2336,11 +2369,12 @@ df_urec_bb_local_compute (struct dataflow *dflow, unsigned int bb_index)
|
||||
struct df_ref *def;
|
||||
|
||||
for (def = df_get_artificial_defs (df, bb_index); def; def = def->next_ref)
|
||||
{
|
||||
unsigned int regno = DF_REF_REGNO (def);
|
||||
bitmap_set_bit (bb_info->gen, regno);
|
||||
}
|
||||
|
||||
if (DF_REF_FLAGS (def) & DF_REF_AT_TOP)
|
||||
{
|
||||
unsigned int regno = DF_REF_REGNO (def);
|
||||
bitmap_set_bit (bb_info->gen, regno);
|
||||
}
|
||||
|
||||
FOR_BB_INSNS (bb, insn)
|
||||
{
|
||||
if (INSN_P (insn))
|
||||
@ -2357,6 +2391,14 @@ df_urec_bb_local_compute (struct dataflow *dflow, unsigned int bb_index)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (def = df_get_artificial_defs (df, bb_index); def; def = def->next_ref)
|
||||
if ((DF_REF_FLAGS (def) & DF_REF_AT_TOP) == 0)
|
||||
{
|
||||
unsigned int regno = DF_REF_REGNO (def);
|
||||
bitmap_set_bit (bb_info->gen, regno);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -2424,32 +2466,8 @@ df_urec_init (struct dataflow *dflow, bitmap all_blocks)
|
||||
{
|
||||
struct df_urec_bb_info *bb_info = df_urec_get_bb_info (dflow, bb_index);
|
||||
|
||||
/* FIXME: This is a hack, it has been copied over from
|
||||
make_accurate_live_analysis by Vlad. Most likely it is necessary
|
||||
because the generation of gen and kill information for hardware
|
||||
registers in ur is a subset of what is really necessary and what
|
||||
is done for the lr problem. */
|
||||
|
||||
/* Inside the register allocator, partial availability is only
|
||||
allowed for the psuedo registers. To implement this, the rr is
|
||||
initially iored with a mask ones for the hard registers and zeros
|
||||
for the pseudos before being iterated. This means that each
|
||||
hardware register will be live unless explicitly killed by some
|
||||
statement. Eventually most of these bit will die because the
|
||||
results of rr are anded with the results of lr before being used.
|
||||
Outside of register allocation, a more conservative strategy of
|
||||
completely ignoring the unintialized registers is imployed in the
|
||||
finalizer function. */
|
||||
if (df_state & DF_SCAN_GLOBAL)
|
||||
{
|
||||
bitmap_ior (bb_info->out, bb_info->gen, df_all_hard_regs);
|
||||
bitmap_copy (bb_info->in, df_all_hard_regs);
|
||||
}
|
||||
else
|
||||
{
|
||||
bitmap_copy (bb_info->out, bb_info->gen);
|
||||
bitmap_clear (bb_info->in);
|
||||
}
|
||||
bitmap_copy (bb_info->out, bb_info->gen);
|
||||
bitmap_clear (bb_info->in);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2489,12 +2507,6 @@ df_urec_local_finalize (struct dataflow *dflow, bitmap all_blocks)
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!(df_state & DF_SCAN_GLOBAL))
|
||||
{
|
||||
bitmap_ior_into (bb_info->in, df_all_hard_regs);
|
||||
bitmap_ior_into (bb_info->out, df_all_hard_regs);
|
||||
}
|
||||
|
||||
/* No register may reach a location where it is not used. Thus
|
||||
we trim the rr result to the places where it is used. */
|
||||
bitmap_and_into (bb_info->in, bb_lr_info->in);
|
||||
@ -2830,7 +2842,7 @@ df_chain_create_bb_process_use (struct dataflow *dflow,
|
||||
|
||||
while (use)
|
||||
{
|
||||
/* Do not want to go thur this for an uninitialized var. */
|
||||
/* Do not want to go through this for an uninitialized var. */
|
||||
unsigned int uregno = DF_REF_REGNO (use);
|
||||
int count = DF_REG_DEF_GET (df, uregno)->n_refs;
|
||||
if (count)
|
||||
@ -2891,14 +2903,15 @@ df_chain_create_bb (struct dataflow *dflow,
|
||||
#endif
|
||||
|
||||
for (def = df_get_artificial_defs (df, bb_index); def; def = def->next_ref)
|
||||
{
|
||||
unsigned int dregno = DF_REF_REGNO (def);
|
||||
bitmap_clear_range (cpy,
|
||||
DF_REG_DEF_GET (df, dregno)->begin,
|
||||
DF_REG_DEF_GET (df, dregno)->n_refs);
|
||||
if (! (DF_REF_FLAGS (def) & DF_REF_CLOBBER))
|
||||
bitmap_set_bit (cpy, DF_REF_ID (def));
|
||||
}
|
||||
if (DF_REF_FLAGS (def) & DF_REF_AT_TOP)
|
||||
{
|
||||
unsigned int dregno = DF_REF_REGNO (def);
|
||||
bitmap_clear_range (cpy,
|
||||
DF_REG_DEF_GET (df, dregno)->begin,
|
||||
DF_REG_DEF_GET (df, dregno)->n_refs);
|
||||
if (! (DF_REF_FLAGS (def) & DF_REF_CLOBBER))
|
||||
bitmap_set_bit (cpy, DF_REF_ID (def));
|
||||
}
|
||||
|
||||
/* Process the regular instructions next. */
|
||||
FOR_BB_INSNS (bb, insn)
|
||||
@ -3136,8 +3149,14 @@ df_ri_bb_compute (struct dataflow *dflow, unsigned int bb_index, bitmap live)
|
||||
{
|
||||
unsigned int uregno = DF_REF_REGNO (use);
|
||||
|
||||
/* This register is now live. */
|
||||
bitmap_set_bit (live, uregno);
|
||||
if (!bitmap_bit_p (live, uregno))
|
||||
{
|
||||
use->flags |= DF_REF_DIES_AFTER_THIS_USE;
|
||||
/* This register is now live. */
|
||||
bitmap_set_bit (live, uregno);
|
||||
}
|
||||
else
|
||||
use->flags &= ~DF_REF_DIES_AFTER_THIS_USE;
|
||||
}
|
||||
|
||||
/* Increment lifetimes of all live registers. */
|
||||
|
207
gcc/df-scan.c
207
gcc/df-scan.c
@ -46,6 +46,9 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
#include "sbitmap.h"
|
||||
#include "bitmap.h"
|
||||
#include "timevar.h"
|
||||
#include "tree.h"
|
||||
#include "target.h"
|
||||
#include "target-def.h"
|
||||
#include "df.h"
|
||||
|
||||
#ifndef HAVE_epilogue
|
||||
@ -82,8 +85,6 @@ bitmap df_invalidated_by_call = NULL;
|
||||
/* Initialize ur_in and ur_out as if all hard registers were partially
|
||||
available. */
|
||||
|
||||
bitmap df_all_hard_regs = NULL;
|
||||
|
||||
static void df_ref_record (struct dataflow *, rtx, rtx *,
|
||||
basic_block, rtx, enum df_ref_type,
|
||||
enum df_ref_flags, bool record_live);
|
||||
@ -99,6 +100,7 @@ static void df_refs_record (struct dataflow *, bitmap);
|
||||
static struct df_ref *df_ref_create_structure (struct dataflow *, rtx, rtx *,
|
||||
basic_block, rtx, enum df_ref_type,
|
||||
enum df_ref_flags);
|
||||
static void df_record_entry_block_defs (struct dataflow *);
|
||||
static void df_record_exit_block_uses (struct dataflow *);
|
||||
static void df_grow_reg_info (struct dataflow *, struct df_ref_info *);
|
||||
static void df_grow_ref_info (struct df_ref_info *, unsigned int);
|
||||
@ -148,6 +150,7 @@ df_scan_free_internal (struct dataflow *dflow)
|
||||
dflow->block_info_size = 0;
|
||||
|
||||
BITMAP_FREE (df->hardware_regs_used);
|
||||
BITMAP_FREE (df->entry_block_defs);
|
||||
BITMAP_FREE (df->exit_block_uses);
|
||||
|
||||
free_alloc_pool (dflow->block_pool);
|
||||
@ -252,6 +255,7 @@ df_scan_alloc (struct dataflow *dflow, bitmap blocks_to_rescan)
|
||||
}
|
||||
|
||||
df->hardware_regs_used = BITMAP_ALLOC (NULL);
|
||||
df->entry_block_defs = BITMAP_ALLOC (NULL);
|
||||
df->exit_block_uses = BITMAP_ALLOC (NULL);
|
||||
}
|
||||
|
||||
@ -284,12 +288,12 @@ df_scan_dump (struct dataflow *dflow ATTRIBUTE_UNUSED, FILE *file ATTRIBUTE_UNUS
|
||||
struct df *df = dflow->df;
|
||||
int i;
|
||||
|
||||
fprintf (file, " all hard regs \t");
|
||||
dump_bitmap (file, df_all_hard_regs);
|
||||
fprintf (file, " invalidated by call \t");
|
||||
dump_bitmap (file, df_invalidated_by_call);
|
||||
fprintf (file, " hardware regs used \t");
|
||||
dump_bitmap (file, df->hardware_regs_used);
|
||||
fprintf (file, " entry block uses \t");
|
||||
dump_bitmap (file, df->entry_block_defs);
|
||||
fprintf (file, " exit block uses \t");
|
||||
dump_bitmap (file, df->exit_block_uses);
|
||||
fprintf (file, " regs ever live \t");
|
||||
@ -1247,7 +1251,7 @@ df_uses_record (struct dataflow *dflow, rtx *loc, enum df_ref_type ref_type,
|
||||
{
|
||||
rtx dst = SET_DEST (x);
|
||||
gcc_assert (!(flags & DF_REF_IN_NOTE));
|
||||
df_uses_record (dflow, &SET_SRC (x), DF_REF_REG_USE, bb, insn, 0);
|
||||
df_uses_record (dflow, &SET_SRC (x), DF_REF_REG_USE, bb, insn, flags);
|
||||
|
||||
switch (GET_CODE (dst))
|
||||
{
|
||||
@ -1256,7 +1260,7 @@ df_uses_record (struct dataflow *dflow, rtx *loc, enum df_ref_type ref_type,
|
||||
{
|
||||
df_uses_record (dflow, &SUBREG_REG (dst),
|
||||
DF_REF_REG_USE, bb,
|
||||
insn, DF_REF_READ_WRITE);
|
||||
insn, flags | DF_REF_READ_WRITE);
|
||||
break;
|
||||
}
|
||||
/* Fall through. */
|
||||
@ -1269,7 +1273,7 @@ df_uses_record (struct dataflow *dflow, rtx *loc, enum df_ref_type ref_type,
|
||||
case MEM:
|
||||
df_uses_record (dflow, &XEXP (dst, 0),
|
||||
DF_REF_REG_MEM_STORE,
|
||||
bb, insn, 0);
|
||||
bb, insn, flags);
|
||||
break;
|
||||
case STRICT_LOW_PART:
|
||||
{
|
||||
@ -1290,9 +1294,9 @@ df_uses_record (struct dataflow *dflow, rtx *loc, enum df_ref_type ref_type,
|
||||
DF_REF_REG_USE, bb, insn,
|
||||
DF_REF_READ_WRITE);
|
||||
df_uses_record (dflow, &XEXP (dst, 1),
|
||||
DF_REF_REG_USE, bb, insn, 0);
|
||||
DF_REF_REG_USE, bb, insn, flags);
|
||||
df_uses_record (dflow, &XEXP (dst, 2),
|
||||
DF_REF_REG_USE, bb, insn, 0);
|
||||
DF_REF_REG_USE, bb, insn, flags);
|
||||
dst = XEXP (dst, 0);
|
||||
break;
|
||||
default:
|
||||
@ -1342,7 +1346,7 @@ df_uses_record (struct dataflow *dflow, rtx *loc, enum df_ref_type ref_type,
|
||||
|
||||
for (j = 0; j < ASM_OPERANDS_INPUT_LENGTH (x); j++)
|
||||
df_uses_record (dflow, &ASM_OPERANDS_INPUT (x, j),
|
||||
DF_REF_REG_USE, bb, insn, 0);
|
||||
DF_REF_REG_USE, bb, insn, flags);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
@ -1355,8 +1359,9 @@ df_uses_record (struct dataflow *dflow, rtx *loc, enum df_ref_type ref_type,
|
||||
case PRE_MODIFY:
|
||||
case POST_MODIFY:
|
||||
/* Catch the def of the register being modified. */
|
||||
flags |= DF_REF_READ_WRITE;
|
||||
df_ref_record (dflow, XEXP (x, 0), &XEXP (x, 0), bb, insn,
|
||||
DF_REF_REG_DEF, DF_REF_READ_WRITE, true);
|
||||
DF_REF_REG_DEF, flags, true);
|
||||
|
||||
/* ... Fall through to handle uses ... */
|
||||
|
||||
@ -1562,42 +1567,66 @@ df_bb_refs_record (struct dataflow *dflow, basic_block bb)
|
||||
{
|
||||
unsigned int i;
|
||||
/* Mark the registers that will contain data for the handler. */
|
||||
if (current_function_calls_eh_return)
|
||||
for (i = 0; ; ++i)
|
||||
{
|
||||
unsigned regno = EH_RETURN_DATA_REGNO (i);
|
||||
if (regno == INVALID_REGNUM)
|
||||
break;
|
||||
df_ref_record (dflow, regno_reg_rtx[i], ®no_reg_rtx[i], bb, NULL,
|
||||
DF_REF_REG_DEF, DF_REF_ARTIFICIAL | DF_REF_AT_TOP, false);
|
||||
}
|
||||
for (i = 0; ; ++i)
|
||||
{
|
||||
unsigned regno = EH_RETURN_DATA_REGNO (i);
|
||||
if (regno == INVALID_REGNUM)
|
||||
break;
|
||||
df_ref_record (dflow, regno_reg_rtx[i], ®no_reg_rtx[i], bb, NULL,
|
||||
DF_REF_REG_DEF, DF_REF_ARTIFICIAL | DF_REF_AT_TOP,
|
||||
false);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef EH_USES
|
||||
/* This code is putting in a artificial ref for the use at the TOP
|
||||
of the block that receives the exception. It is too cumbersome
|
||||
to actually put the ref on the edge. We could either model this
|
||||
at the top of the receiver block or the bottom of the sender
|
||||
block.
|
||||
|
||||
The bottom of the sender block is problematic because not all
|
||||
out-edges of the a block are eh-edges. However, it is true that
|
||||
all edges into a block are either eh-edges or none of them are
|
||||
eh-edges. Thus, we can model this at the top of the eh-receiver
|
||||
for all of the edges at once. */
|
||||
if ((df->flags & DF_HARD_REGS)
|
||||
&& df_has_eh_preds (bb))
|
||||
{
|
||||
#ifdef EH_USES
|
||||
unsigned int i;
|
||||
/* This code is putting in a artificial ref for the use at the
|
||||
TOP of the block that receives the exception. It is too
|
||||
cumbersome to actually put the ref on the edge. We could
|
||||
either model this at the top of the receiver block or the
|
||||
bottom of the sender block.
|
||||
|
||||
The bottom of the sender block is problematic because not all
|
||||
out-edges of the a block are eh-edges. However, it is true
|
||||
that all edges into a block are either eh-edges or none of
|
||||
them are eh-edges. Thus, we can model this at the top of the
|
||||
eh-receiver for all of the edges at once. */
|
||||
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
|
||||
if (EH_USES (i))
|
||||
df_uses_record (dflow, ®no_reg_rtx[i],
|
||||
DF_REF_REG_USE, EXIT_BLOCK_PTR, NULL,
|
||||
DF_REF_ARTIFICIAL | DF_REF_AT_TOP);
|
||||
}
|
||||
DF_REF_REG_USE, EXIT_BLOCK_PTR, NULL,
|
||||
DF_REF_ARTIFICIAL | DF_REF_AT_TOP);
|
||||
#endif
|
||||
|
||||
/* The following code (down thru the arg_pointer seting APPEARS
|
||||
to be necessary because there is nothing that actually
|
||||
describes what the exception handling code may actually need
|
||||
to keep alive. */
|
||||
if (reload_completed)
|
||||
{
|
||||
if (frame_pointer_needed)
|
||||
{
|
||||
df_uses_record (dflow, ®no_reg_rtx[FRAME_POINTER_REGNUM],
|
||||
DF_REF_REG_USE, bb, NULL, DF_REF_ARTIFICIAL);
|
||||
#if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
|
||||
df_uses_record (dflow, ®no_reg_rtx[HARD_FRAME_POINTER_REGNUM],
|
||||
DF_REF_REG_USE, bb, NULL, DF_REF_ARTIFICIAL);
|
||||
#endif
|
||||
}
|
||||
#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
|
||||
if (fixed_regs[ARG_POINTER_REGNUM])
|
||||
df_uses_record (dflow, ®no_reg_rtx[ARG_POINTER_REGNUM],
|
||||
DF_REF_REG_USE, bb, NULL,
|
||||
DF_REF_ARTIFICIAL);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if ((df->flags & DF_HARD_REGS)
|
||||
&& bb->index >= NUM_FIXED_BLOCKS)
|
||||
{
|
||||
@ -1652,6 +1681,9 @@ df_refs_record (struct dataflow *dflow, bitmap blocks)
|
||||
|
||||
if (bitmap_bit_p (blocks, EXIT_BLOCK))
|
||||
df_record_exit_block_uses (dflow);
|
||||
|
||||
if (bitmap_bit_p (blocks, ENTRY_BLOCK))
|
||||
df_record_entry_block_defs (dflow);
|
||||
}
|
||||
|
||||
|
||||
@ -1679,6 +1711,108 @@ df_mark_reg (rtx reg, void *vset)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Record the (conservative) set of hard registers that are defined on
|
||||
entry to the function. */
|
||||
|
||||
static void
|
||||
df_record_entry_block_defs (struct dataflow * dflow)
|
||||
{
|
||||
unsigned int i;
|
||||
bitmap_iterator bi;
|
||||
rtx r;
|
||||
struct df * df = dflow->df;
|
||||
|
||||
bitmap_clear (df->entry_block_defs);
|
||||
|
||||
if (! (df->flags & DF_HARD_REGS))
|
||||
return;
|
||||
|
||||
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
|
||||
{
|
||||
if (FUNCTION_ARG_REGNO_P (i))
|
||||
#ifdef INCOMING_REGNO
|
||||
bitmap_set_bit (df->entry_block_defs, INCOMING_REGNO (i));
|
||||
#else
|
||||
bitmap_set_bit (df->entry_block_defs, i);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Once the prologue has been generated, all of these registers
|
||||
should just show up in the first regular block. */
|
||||
if (HAVE_prologue && epilogue_completed)
|
||||
{
|
||||
/* Defs for the callee saved registers are inserted so that the
|
||||
pushes have some defining location. */
|
||||
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
|
||||
if ((call_used_regs[i] == 0) && (regs_ever_live[i]))
|
||||
bitmap_set_bit (df->entry_block_defs, i);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (REG_P (INCOMING_RETURN_ADDR_RTX))
|
||||
bitmap_set_bit (df->entry_block_defs, REGNO (INCOMING_RETURN_ADDR_RTX));
|
||||
|
||||
/* If STATIC_CHAIN_INCOMING_REGNUM == STATIC_CHAIN_REGNUM
|
||||
only STATIC_CHAIN_REGNUM is defined. If they are different,
|
||||
we only care about the STATIC_CHAIN_INCOMING_REGNUM. */
|
||||
#ifdef STATIC_CHAIN_INCOMING_REGNUM
|
||||
bitmap_set_bit (df->entry_block_defs, STATIC_CHAIN_INCOMING_REGNUM);
|
||||
#else
|
||||
#ifdef STATIC_CHAIN_REGNUM
|
||||
bitmap_set_bit (df->entry_block_defs, STATIC_CHAIN_REGNUM);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
r = TARGET_STRUCT_VALUE_RTX (current_function_decl, true);
|
||||
if (r && REG_P (r))
|
||||
bitmap_set_bit (df->entry_block_defs, REGNO (r));
|
||||
}
|
||||
|
||||
/* These registers are live everywhere. */
|
||||
if (!reload_completed)
|
||||
{
|
||||
/* Any reference to any pseudo before reload is a potential
|
||||
reference of the frame pointer. */
|
||||
bitmap_set_bit (df->entry_block_defs, FRAME_POINTER_REGNUM);
|
||||
|
||||
#ifdef EH_USES
|
||||
/* The ia-64, the only machine that uses this, does not define these
|
||||
until after reload. */
|
||||
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
|
||||
if (EH_USES (i))
|
||||
{
|
||||
bitmap_set_bit (df->entry_block_defs, i);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
|
||||
/* Pseudos with argument area equivalences may require
|
||||
reloading via the argument pointer. */
|
||||
if (fixed_regs[ARG_POINTER_REGNUM])
|
||||
bitmap_set_bit (df->entry_block_defs, ARG_POINTER_REGNUM);
|
||||
#endif
|
||||
|
||||
#ifdef PIC_OFFSET_TABLE_REGNUM
|
||||
/* Any constant, or pseudo with constant equivalences, may
|
||||
require reloading from memory using the pic register. */
|
||||
if ((unsigned) PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM
|
||||
&& fixed_regs[PIC_OFFSET_TABLE_REGNUM])
|
||||
bitmap_set_bit (df->entry_block_defs, PIC_OFFSET_TABLE_REGNUM);
|
||||
#endif
|
||||
}
|
||||
|
||||
(*targetm.live_on_entry) (df->entry_block_defs);
|
||||
|
||||
EXECUTE_IF_SET_IN_BITMAP (df->entry_block_defs, 0, i, bi)
|
||||
{
|
||||
df_ref_record (dflow, regno_reg_rtx[i], ®no_reg_rtx[i],
|
||||
ENTRY_BLOCK_PTR, NULL,
|
||||
DF_REF_REG_DEF, DF_REF_ARTIFICIAL , false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Record the set of hard registers that are used in the exit block. */
|
||||
|
||||
static void
|
||||
@ -1827,10 +1961,5 @@ df_hard_reg_init (void)
|
||||
if (TEST_HARD_REG_BIT (regs_invalidated_by_call, i))
|
||||
bitmap_set_bit (df_invalidated_by_call, i);
|
||||
|
||||
df_all_hard_regs = BITMAP_ALLOC (&persistent_obstack);
|
||||
|
||||
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
|
||||
bitmap_set_bit (df_all_hard_regs, i);
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
15
gcc/df.h
15
gcc/df.h
@ -211,7 +211,12 @@ enum df_ref_flags
|
||||
DF_REF_IN_NOTE = 16,
|
||||
|
||||
/* This flag is set if this ref is really a clobber, and not a def. */
|
||||
DF_REF_CLOBBER = 32
|
||||
DF_REF_CLOBBER = 32,
|
||||
|
||||
/* True if ref is dead (i.e. the next ref is a def or clobber or
|
||||
the end of the function.) This is only valid the RI problem
|
||||
has been set in this df instance. */
|
||||
DF_REF_DIES_AFTER_THIS_USE = 64
|
||||
};
|
||||
|
||||
|
||||
@ -223,7 +228,10 @@ struct df_ref
|
||||
rtx reg; /* The register referenced. */
|
||||
unsigned int regno; /* The register number referenced. */
|
||||
basic_block bb; /* Basic block containing the instruction. */
|
||||
rtx insn; /* Insn containing ref. NB: THIS MAY BE NULL. */
|
||||
|
||||
/* Insn containing ref. This will be null if this is an artificial
|
||||
reference. */
|
||||
rtx insn;
|
||||
rtx *loc; /* The location of the reg. */
|
||||
struct df_link *chain; /* Head of def-use, use-def. */
|
||||
unsigned int id; /* Location in table. */
|
||||
@ -316,6 +324,7 @@ struct df
|
||||
struct df_insn_info **insns; /* Insn table, indexed by insn UID. */
|
||||
unsigned int insns_size; /* Size of insn table. */
|
||||
bitmap hardware_regs_used; /* The set of hardware registers used. */
|
||||
bitmap entry_block_defs; /* The set of hardware registers live on entry to the function. */
|
||||
bitmap exit_block_uses; /* The set of hardware registers used in exit block. */
|
||||
};
|
||||
|
||||
@ -422,8 +431,6 @@ extern bitmap df_invalidated_by_call;
|
||||
/* Initialize ur_in and ur_out as if all hard registers were partially
|
||||
available. */
|
||||
|
||||
extern bitmap df_all_hard_regs;
|
||||
|
||||
/* The way that registers are processed, especially hard registers,
|
||||
changes as the compilation proceeds. These states are passed to
|
||||
df_set_state to control this processing. */
|
||||
|
@ -4481,6 +4481,15 @@ as the @code{sibcall} md pattern can not fail, or fall over to a
|
||||
may vary greatly between different architectures.
|
||||
@end deftypefn
|
||||
|
||||
@deftypefn {Target Hook} void TARGET_EXTRA_LIVE_ON_ENTRY (bitmap *@var{regs})
|
||||
Add any hard registers to @var{regs} that are live on entry to the
|
||||
function. This hook only needs to be defined to provide registers that
|
||||
cannot be found by examination of FUNCTION_ARG_REGNO_P, the callee saved
|
||||
registers, STATIC_CHAIN_INCOMING_REGNUM, STATIC_CHAIN_REGNUM,
|
||||
TARGET_STRUCT_VALUE_RTX, FRAME_POINTER_REGNUM, EH_USES,
|
||||
FRAME_POINTER_REGNUM, ARG_POINTER_REGNUM, and the PIC_OFFSET_TABLE_REGNUM.
|
||||
@end deftypefn
|
||||
|
||||
@node Stack Smashing Protection
|
||||
@subsection Stack smashing protection
|
||||
@cindex stack smashing protection
|
||||
|
@ -185,6 +185,10 @@ Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#define TARGET_ASM_FILE_END hook_void_void
|
||||
#endif
|
||||
|
||||
#ifndef TARGET_EXTRA_LIVE_ON_ENTRY
|
||||
#define TARGET_EXTRA_LIVE_ON_ENTRY hook_void_bitmap
|
||||
#endif
|
||||
|
||||
#ifndef TARGET_ASM_FILE_START_APP_OFF
|
||||
#define TARGET_ASM_FILE_START_APP_OFF false
|
||||
#endif
|
||||
@ -625,6 +629,7 @@ Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
TARGET_INVALID_BINARY_OP, \
|
||||
TARGET_SECONDARY_RELOAD, \
|
||||
TARGET_CXX, \
|
||||
TARGET_EXTRA_LIVE_ON_ENTRY, \
|
||||
TARGET_UNWIND_TABLES_DEFAULT, \
|
||||
TARGET_HAVE_NAMED_SECTIONS, \
|
||||
TARGET_HAVE_CTORS_DTORS, \
|
||||
|
@ -703,6 +703,11 @@ struct gcc_target
|
||||
target modifications). */
|
||||
void (*adjust_class_at_definition) (tree type);
|
||||
} cxx;
|
||||
|
||||
/* For targets that need to mark extra registers as live on entry to
|
||||
the function, they should define this target hook and set their
|
||||
bits in the bitmap passed in. */
|
||||
void (*live_on_entry) (bitmap);
|
||||
|
||||
/* True if unwinding tables should be generated by default. */
|
||||
bool unwind_tables_default;
|
||||
|
@ -337,6 +337,11 @@ hook_int_CUMULATIVE_ARGS_mode_tree_bool_0 (
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
hook_void_bitmap (bitmap regs ATTRIBUTE_UNUSED)
|
||||
{
|
||||
}
|
||||
|
||||
const char *
|
||||
hook_invalid_arg_for_unprototyped_fn (
|
||||
tree typelist ATTRIBUTE_UNUSED,
|
||||
|
@ -74,3 +74,4 @@ extern rtx default_internal_arg_pointer (void);
|
||||
extern enum reg_class default_secondary_reload (bool, rtx, enum reg_class,
|
||||
enum machine_mode,
|
||||
secondary_reload_info *);
|
||||
extern void hook_void_bitmap (bitmap);
|
||||
|
Loading…
Reference in New Issue
Block a user