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:
Daniel Berlin 2006-01-27 22:23:32 +00:00 committed by Kenneth Zadeck
parent 7744bbe369
commit 912f2dacdf
15 changed files with 442 additions and 190 deletions

View File

@ -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

View File

@ -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) \

View File

@ -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 */

View File

@ -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);

View File

@ -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"

View File

@ -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;

View File

@ -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

View File

@ -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. */

View File

@ -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], &regno_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], &regno_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, &regno_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, &regno_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, &regno_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, &regno_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], &regno_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;
}

View File

@ -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. */

View File

@ -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

View File

@ -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, \

View File

@ -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;

View File

@ -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,

View File

@ -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);