fwprop.c (update_df): Support width and offset parameters of df_ref_create.

2008-03-05  Kenneth Zadeck <zadeck@naturalbridge.com>

	* fwprop.c (update_df): Support width and offset parameters of
	df_ref_create.
	* ra-conflict.c (mark_reg_store, clear_reg_in_live,
	global_conflicts): Change DF_REF_EXTRACT to either
	DF_REF_ZERO_EXTRACT or DF_REF_SIGN_EXTRACT.  Change
	DF_REF_STRICT_LOWER_PART to DF_REF_STRICT_LOW_PART.
	* df-scan.c (df_ref_record, df_defs_record,
	df_ref_create_structure, df_def_record_1, df_uses_record,
	df_get_conditional_uses, df_get_call_refs, df_insn_refs_collect,
	df_bb_refs_collect, df_entry_block_defs_collect,
	df_exit_block_uses_collect): Support new width and offset fields.
	(ref_extract_pool): New storage pool.
	(df_free_ref): New function.
	(df_reg_chain_unlink, df_free_collection_rec,
	df_sort_and_compress_refs): Call df_free_ref.
	(df_ref_equal_p, df_ref_compare): Compare offset and width fields
	of df_ref_extract.
	(df_ref_create_structure): Allocate df_ref_extract if offset and
	width fields are used.
	(df_def_record_1): Get offset and width from ZERO_EXTRACT.
	(df_uses_record): Get offset and width from ZERO_EXTRACT 
	and SIGN_EXTRACT.
	* global.c (build_insn_chain): Change DF_REF_EXTRACT to either
	DF_REF_ZERO_EXTRACT or DF_REF_SIGN_EXTRACT.  Change
	DF_REF_STRICT_LOWER_PART to DF_REF_STRICT_LOW_PART.
	* df.h (df_ref_flags): Change DF_REF_EXTRACT to either
	DF_REF_ZERO_EXTRACT or DF_REF_SIGN_EXTRACT.  Change
	DF_REF_STRICT_LOWER_PART to DF_REF_STRICT_LOW_PART.
	(df_ref_extract): New structure.
	(DF_REF_WIDTH, DF_REF_OFFSET): New macros.
	(df_ref_create): Add width and offset parameters.

From-SVN: r132962
This commit is contained in:
Kenneth Zadeck 2008-03-06 00:21:34 +00:00
parent 256fe3d795
commit ca9052ce17
6 changed files with 290 additions and 101 deletions

View File

@ -1,3 +1,37 @@
2008-03-05 Kenneth Zadeck <zadeck@naturalbridge.com>
* fwprop.c (update_df): Support width and offset parameters of
df_ref_create.
* ra-conflict.c (mark_reg_store, clear_reg_in_live,
global_conflicts): Change DF_REF_EXTRACT to either
DF_REF_ZERO_EXTRACT or DF_REF_SIGN_EXTRACT. Change
DF_REF_STRICT_LOWER_PART to DF_REF_STRICT_LOW_PART.
* df-scan.c (df_ref_record, df_defs_record,
df_ref_create_structure, df_def_record_1, df_uses_record,
df_get_conditional_uses, df_get_call_refs, df_insn_refs_collect,
df_bb_refs_collect, df_entry_block_defs_collect,
df_exit_block_uses_collect): Support new width and offset fields.
(ref_extract_pool): New storage pool.
(df_free_ref): New function.
(df_reg_chain_unlink, df_free_collection_rec,
df_sort_and_compress_refs): Call df_free_ref.
(df_ref_equal_p, df_ref_compare): Compare offset and width fields
of df_ref_extract.
(df_ref_create_structure): Allocate df_ref_extract if offset and
width fields are used.
(df_def_record_1): Get offset and width from ZERO_EXTRACT.
(df_uses_record): Get offset and width from ZERO_EXTRACT
and SIGN_EXTRACT.
* global.c (build_insn_chain): Change DF_REF_EXTRACT to either
DF_REF_ZERO_EXTRACT or DF_REF_SIGN_EXTRACT. Change
DF_REF_STRICT_LOWER_PART to DF_REF_STRICT_LOW_PART.
* df.h (df_ref_flags): Change DF_REF_EXTRACT to either
DF_REF_ZERO_EXTRACT or DF_REF_SIGN_EXTRACT. Change
DF_REF_STRICT_LOWER_PART to DF_REF_STRICT_LOW_PART.
(df_ref_extract): New structure.
(DF_REF_WIDTH, DF_REF_OFFSET): New macros.
(df_ref_create): Add width and offset parameters.
2008-03-05 Richard Guenther <rguenther@suse.de>
* tree-ssa-structalias.c (get_constraint_for_component_ref):
@ -135,6 +169,7 @@
transformations for modes that have signed zeros.
* ifcvt.c (noce_try_abs): Ditto.
>>>>>>> .r132956
2008-03-04 Joseph Myers <joseph@codesourcery.com>
* config/i386/i386.c (override_options): Force

View File

@ -95,7 +95,7 @@ static struct df_mw_hardreg * df_null_mw_rec[1];
static void df_ref_record (struct df_collection_rec *,
rtx, rtx *,
basic_block, rtx, enum df_ref_type,
enum df_ref_flags);
enum df_ref_flags, int, int);
static void df_def_record_1 (struct df_collection_rec *,
rtx, basic_block, rtx,
enum df_ref_flags);
@ -104,11 +104,11 @@ static void df_defs_record (struct df_collection_rec *,
enum df_ref_flags);
static void df_uses_record (struct df_collection_rec *,
rtx *, enum df_ref_type,
basic_block, rtx, enum df_ref_flags);
basic_block, rtx, enum df_ref_flags, int, int);
static struct df_ref *df_ref_create_structure (struct df_collection_rec *, rtx, rtx *,
basic_block, rtx, enum df_ref_type,
enum df_ref_flags);
enum df_ref_flags, int, int);
static void df_insn_refs_collect (struct df_collection_rec*,
basic_block, rtx);
@ -160,6 +160,7 @@ static bool regs_ever_live[FIRST_PSEUDO_REGISTER];
struct df_scan_problem_data
{
alloc_pool ref_pool;
alloc_pool ref_extract_pool;
alloc_pool insn_pool;
alloc_pool reg_pool;
alloc_pool mw_reg_pool;
@ -214,6 +215,7 @@ df_scan_free_internal (void)
free_alloc_pool (df_scan->block_pool);
free_alloc_pool (problem_data->ref_pool);
free_alloc_pool (problem_data->ref_extract_pool);
free_alloc_pool (problem_data->insn_pool);
free_alloc_pool (problem_data->reg_pool);
free_alloc_pool (problem_data->mw_reg_pool);
@ -296,6 +298,9 @@ df_scan_alloc (bitmap all_blocks ATTRIBUTE_UNUSED)
problem_data->ref_pool
= create_alloc_pool ("df_scan_ref pool",
sizeof (struct df_ref), block_size);
problem_data->ref_extract_pool
= create_alloc_pool ("df_scan_ref extract pool",
sizeof (struct df_ref_extract), block_size);
problem_data->insn_pool
= create_alloc_pool ("df_scan_insn pool",
sizeof (struct df_insn_info), block_size);
@ -608,13 +613,19 @@ df_scan_blocks (void)
/* Create a new ref of type DF_REF_TYPE for register REG at address
LOC within INSN of BB. */
LOC within INSN of BB. This function is only used externally.
If the REF_FLAGS field contain DF_REF_SIGN_EXTRACT or
DF_REF_ZERO_EXTRACT. WIDTH and OFFSET are used to access the fields
if they were constants. Otherwise they should be -1 if those flags
were set. */
struct df_ref *
df_ref_create (rtx reg, rtx *loc, rtx insn,
basic_block bb,
enum df_ref_type ref_type,
enum df_ref_flags ref_flags)
enum df_ref_flags ref_flags,
int width, int offset)
{
struct df_ref *ref;
struct df_reg_info **reg_info;
@ -629,7 +640,7 @@ df_ref_create (rtx reg, rtx *loc, rtx insn,
/* You cannot hack artificial refs. */
gcc_assert (insn);
ref = df_ref_create_structure (NULL, reg, loc, bb, insn,
ref_type, ref_flags);
ref_type, ref_flags, width, offset);
if (DF_REF_TYPE (ref) == DF_REF_REG_DEF)
{
@ -727,6 +738,18 @@ df_ref_create (rtx reg, rtx *loc, rtx insn,
UTILITIES TO CREATE AND DESTROY REFS AND CHAINS.
----------------------------------------------------------------------------*/
static void
df_free_ref (struct df_ref *ref)
{
struct df_scan_problem_data *problem_data
= (struct df_scan_problem_data *) df_scan->problem_data;
if (DF_REF_FLAGS_IS_SET (ref, DF_REF_SIGN_EXTRACT | DF_REF_ZERO_EXTRACT))
pool_free (problem_data->ref_extract_pool, (struct df_ref_extract *)ref);
else
pool_free (problem_data->ref_pool, ref);
}
/* Unlink and delete REF at the reg_use, reg_eq_use or reg_def chain.
Also delete the def-use or use-def chain if it exists. */
@ -736,8 +759,6 @@ df_reg_chain_unlink (struct df_ref *ref)
{
struct df_ref *next = DF_REF_NEXT_REG (ref);
struct df_ref *prev = DF_REF_PREV_REG (ref);
struct df_scan_problem_data *problem_data
= (struct df_scan_problem_data *) df_scan->problem_data;
int id = DF_REF_ID (ref);
struct df_reg_info *reg_info;
struct df_ref **refs = NULL;
@ -808,7 +829,7 @@ df_reg_chain_unlink (struct df_ref *ref)
if (next)
DF_REF_PREV_REG (next) = prev;
pool_free (problem_data->ref_pool, ref);
df_free_ref (ref);
}
@ -1058,13 +1079,13 @@ df_free_collection_rec (struct df_collection_rec *collection_rec)
if (collection_rec->def_vec)
for (ref = collection_rec->def_vec; *ref; ref++)
pool_free (problem_data->ref_pool, *ref);
df_free_ref (*ref);
if (collection_rec->use_vec)
for (ref = collection_rec->use_vec; *ref; ref++)
pool_free (problem_data->ref_pool, *ref);
df_free_ref (*ref);
if (collection_rec->eq_use_vec)
for (ref = collection_rec->eq_use_vec; *ref; ref++)
pool_free (problem_data->ref_pool, *ref);
df_free_ref (*ref);
if (collection_rec->mw_vec)
for (mw = collection_rec->mw_vec; *mw; mw++)
pool_free (problem_data->mw_reg_pool, *mw);
@ -2045,7 +2066,7 @@ df_notes_rescan (rtx insn)
case REG_EQUAL:
df_uses_record (&collection_rec,
&XEXP (note, 0), DF_REF_REG_USE,
bb, insn, DF_REF_IN_NOTE);
bb, insn, DF_REF_IN_NOTE, -1, -1);
default:
break;
}
@ -2115,6 +2136,16 @@ df_ref_equal_p (struct df_ref *ref1, struct df_ref *ref2)
{
if (!ref2)
return false;
/* The two flag tests here are only to make sure we do not look at
the offset and width if they are not there. The flags are
compared in the next set of tests. */
if ((DF_REF_FLAGS_IS_SET (ref1, DF_REF_SIGN_EXTRACT | DF_REF_ZERO_EXTRACT))
&& (DF_REF_FLAGS_IS_SET (ref2, DF_REF_SIGN_EXTRACT | DF_REF_ZERO_EXTRACT))
&& ((DF_REF_OFFSET (ref1) != DF_REF_OFFSET (ref2))
|| (DF_REF_WIDTH (ref1) != DF_REF_WIDTH (ref2))))
return false;
return (ref1 == ref2) ||
(DF_REF_REG (ref1) == DF_REF_REG (ref2)
&& DF_REF_REGNO (ref1) == DF_REF_REGNO (ref2)
@ -2163,6 +2194,16 @@ df_ref_compare (const void *r1, const void *r2)
else
return 1;
}
/* The flags are the same at this point so it is safe to only look
at ref1. */
if (DF_REF_FLAGS_IS_SET (ref1, DF_REF_SIGN_EXTRACT | DF_REF_ZERO_EXTRACT))
{
if (DF_REF_OFFSET (ref1) != DF_REF_OFFSET (ref2))
return DF_REF_OFFSET (ref1) - DF_REF_OFFSET (ref2);
if (DF_REF_WIDTH (ref1) != DF_REF_WIDTH (ref2))
return DF_REF_WIDTH (ref1) - DF_REF_WIDTH (ref2);
}
return 0;
}
@ -2179,8 +2220,6 @@ df_swap_refs (struct df_ref **ref_vec, int i, int j)
static unsigned int
df_sort_and_compress_refs (struct df_ref **ref_vec, unsigned int count)
{
struct df_scan_problem_data *problem_data
= (struct df_scan_problem_data *) df_scan->problem_data;
unsigned int i;
unsigned int dist = 0;
@ -2215,7 +2254,7 @@ df_sort_and_compress_refs (struct df_ref **ref_vec, unsigned int count)
/* Find the next ref that is not equal to the current ref. */
while (df_ref_equal_p (ref_vec[i], ref_vec[i + dist + 1]))
{
pool_free (problem_data->ref_pool, ref_vec[i + dist + 1]);
df_free_ref (ref_vec[i + dist + 1]);
dist++;
}
/* Copy it down to the next position. */
@ -2541,21 +2580,34 @@ df_refs_add_to_chains (struct df_collection_rec *collection_rec,
}
/* Allocate a ref and initialize its fields. */
/* Allocate a ref and initialize its fields.
If the REF_FLAGS field contain DF_REF_SIGN_EXTRACT or
DF_REF_ZERO_EXTRACT. WIDTH and OFFSET are used to access the fields
if they were constants. Otherwise they should be -1 if those flags
were set. */
static struct df_ref *
df_ref_create_structure (struct df_collection_rec *collection_rec,
rtx reg, rtx *loc,
basic_block bb, rtx insn,
enum df_ref_type ref_type,
enum df_ref_flags ref_flags)
enum df_ref_flags ref_flags,
int width, int offset)
{
struct df_ref *this_ref;
int regno = REGNO (GET_CODE (reg) == SUBREG ? SUBREG_REG (reg) : reg);
struct df_scan_problem_data *problem_data
= (struct df_scan_problem_data *) df_scan->problem_data;
this_ref = pool_alloc (problem_data->ref_pool);
if (ref_flags & (DF_REF_SIGN_EXTRACT | DF_REF_ZERO_EXTRACT))
{
this_ref = pool_alloc (problem_data->ref_extract_pool);
DF_REF_WIDTH (this_ref) = width;
DF_REF_OFFSET (this_ref) = offset;
}
else
this_ref = pool_alloc (problem_data->ref_pool);
DF_REF_ID (this_ref) = -1;
DF_REF_REG (this_ref) = reg;
DF_REF_REGNO (this_ref) = regno;
@ -2604,14 +2656,21 @@ df_ref_create_structure (struct df_collection_rec *collection_rec,
/* Create new references of type DF_REF_TYPE for each part of register REG
at address LOC within INSN of BB. */
at address LOC within INSN of BB.
If the REF_FLAGS field contain DF_REF_SIGN_EXTRACT or
DF_REF_ZERO_EXTRACT. WIDTH and OFFSET are used to access the fields
if they were constants. Otherwise they should be -1 if those flags
were set. */
static void
df_ref_record (struct df_collection_rec *collection_rec,
rtx reg, rtx *loc,
basic_block bb, rtx insn,
enum df_ref_type ref_type,
enum df_ref_flags ref_flags)
enum df_ref_flags ref_flags,
int width, int offset)
{
unsigned int regno;
@ -2660,7 +2719,7 @@ df_ref_record (struct df_collection_rec *collection_rec,
for (i = regno; i < endregno; i++)
{
ref = df_ref_create_structure (collection_rec, regno_reg_rtx[i], loc,
bb, insn, ref_type, ref_flags);
bb, insn, ref_type, ref_flags, width, offset);
gcc_assert (ORIGINAL_REGNO (DF_REF_REG (ref)) == i);
}
@ -2669,7 +2728,7 @@ df_ref_record (struct df_collection_rec *collection_rec,
{
struct df_ref *ref;
ref = df_ref_create_structure (collection_rec, reg, loc, bb, insn,
ref_type, ref_flags);
ref_type, ref_flags, width, offset);
}
}
@ -2703,6 +2762,8 @@ df_def_record_1 (struct df_collection_rec *collection_rec,
{
rtx *loc;
rtx dst;
int offset = -1;
int width = -1;
/* We may recursively call ourselves on EXPR_LIST when dealing with PARALLEL
construct. */
@ -2730,16 +2791,24 @@ df_def_record_1 (struct df_collection_rec *collection_rec,
return;
}
/* Maybe, we should flag the use of STRICT_LOW_PART somehow. It might
be handy for the reg allocator. */
while (GET_CODE (dst) == STRICT_LOW_PART
|| GET_CODE (dst) == ZERO_EXTRACT)
if (GET_CODE (dst) == STRICT_LOW_PART)
{
flags |= DF_REF_READ_WRITE | DF_REF_PARTIAL;
if (GET_CODE (dst) == ZERO_EXTRACT)
flags |= DF_REF_EXTRACT;
else
flags |= DF_REF_STRICT_LOWER_PART;
flags |= DF_REF_READ_WRITE | DF_REF_PARTIAL | DF_REF_STRICT_LOW_PART;
loc = &XEXP (dst, 0);
dst = *loc;
}
if (GET_CODE (dst) == ZERO_EXTRACT)
{
flags |= DF_REF_READ_WRITE | DF_REF_PARTIAL | DF_REF_ZERO_EXTRACT;
if (GET_CODE (XEXP (dst, 1)) == CONST_INT
&& GET_CODE (XEXP (dst, 2)) == CONST_INT)
{
width = INTVAL (XEXP (dst, 1));
offset = INTVAL (XEXP (dst, 2));
}
loc = &XEXP (dst, 0);
dst = *loc;
@ -2749,13 +2818,13 @@ df_def_record_1 (struct df_collection_rec *collection_rec,
if (REG_P (dst))
{
df_ref_record (collection_rec,
dst, loc, bb, insn, DF_REF_REG_DEF, flags);
dst, loc, bb, insn, DF_REF_REG_DEF, flags, width, offset);
/* We want to keep sp alive everywhere - by making all
writes to sp also use of sp. */
if (REGNO (dst) == STACK_POINTER_REGNUM)
df_ref_record (collection_rec,
dst, NULL, bb, insn, DF_REF_REG_USE, flags);
dst, NULL, bb, insn, DF_REF_REG_USE, flags, width, offset);
}
else if (GET_CODE (dst) == SUBREG && REG_P (SUBREG_REG (dst)))
{
@ -2765,7 +2834,7 @@ df_def_record_1 (struct df_collection_rec *collection_rec,
flags |= DF_REF_SUBREG;
df_ref_record (collection_rec,
dst, loc, bb, insn, DF_REF_REG_DEF, flags);
dst, loc, bb, insn, DF_REF_REG_DEF, flags, width, offset);
}
}
@ -2801,12 +2870,18 @@ df_defs_record (struct df_collection_rec *collection_rec,
}
/* Process all the registers used in the rtx at address LOC. */
/* Process all the registers used in the rtx at address LOC.
If the REF_FLAGS field contain DF_REF_SIGN_EXTRACT or
DF_REF_ZERO_EXTRACT. WIDTH and LOWER are used to access the fields
if they were constants. Otherwise they should be -1 if those flags
were set. */
static void
df_uses_record (struct df_collection_rec *collection_rec,
rtx *loc, enum df_ref_type ref_type,
basic_block bb, rtx insn, enum df_ref_flags flags)
basic_block bb, rtx insn, enum df_ref_flags flags,
int width, int offset)
{
RTX_CODE code;
rtx x;
@ -2837,7 +2912,7 @@ df_uses_record (struct df_collection_rec *collection_rec,
if (MEM_P (XEXP (x, 0)))
df_uses_record (collection_rec,
&XEXP (XEXP (x, 0), 0),
DF_REF_REG_MEM_STORE, bb, insn, flags);
DF_REF_REG_MEM_STORE, bb, insn, flags, width, offset);
/* If we're clobbering a REG then we have a def so ignore. */
return;
@ -2845,7 +2920,7 @@ df_uses_record (struct df_collection_rec *collection_rec,
case MEM:
df_uses_record (collection_rec,
&XEXP (x, 0), DF_REF_REG_MEM_LOAD,
bb, insn, flags & DF_REF_IN_NOTE);
bb, insn, flags & DF_REF_IN_NOTE, width, offset);
return;
case SUBREG:
@ -2855,22 +2930,46 @@ df_uses_record (struct df_collection_rec *collection_rec,
if (!REG_P (SUBREG_REG (x)))
{
loc = &SUBREG_REG (x);
df_uses_record (collection_rec, loc, ref_type, bb, insn, flags);
df_uses_record (collection_rec, loc, ref_type, bb, insn, flags, width, offset);
return;
}
/* ... Fall through ... */
case REG:
df_ref_record (collection_rec,
x, loc, bb, insn, ref_type, flags);
x, loc, bb, insn, ref_type, flags, width, offset);
return;
case SIGN_EXTRACT:
case ZERO_EXTRACT:
{
/* If the parameters to the zero or sign extract are
constants, strip them off and recurse, otherwise there is
no information that we can gain from this operation. */
if (GET_CODE (XEXP (x, 1)) == CONST_INT
&& GET_CODE (XEXP (x, 2)) == CONST_INT)
{
width = INTVAL (XEXP (x, 1));
offset = INTVAL (XEXP (x, 2));
if (code == ZERO_EXTRACT)
flags |= DF_REF_ZERO_EXTRACT;
else
flags |= DF_REF_SIGN_EXTRACT;
df_uses_record (collection_rec,
&XEXP (x, 0), ref_type, bb, insn, flags, width, offset);
return;
}
}
break;
case SET:
{
rtx dst = SET_DEST (x);
gcc_assert (!(flags & DF_REF_IN_NOTE));
df_uses_record (collection_rec,
&SET_SRC (x), DF_REF_REG_USE, bb, insn, flags);
&SET_SRC (x), DF_REF_REG_USE, bb, insn, flags, width, offset);
switch (GET_CODE (dst))
{
@ -2879,7 +2978,7 @@ df_uses_record (struct df_collection_rec *collection_rec,
{
df_uses_record (collection_rec, &SUBREG_REG (dst),
DF_REF_REG_USE, bb, insn,
flags | DF_REF_READ_WRITE | DF_REF_SUBREG);
flags | DF_REF_READ_WRITE | DF_REF_SUBREG, width, offset);
break;
}
/* Fall through. */
@ -2891,7 +2990,7 @@ df_uses_record (struct df_collection_rec *collection_rec,
break;
case MEM:
df_uses_record (collection_rec, &XEXP (dst, 0),
DF_REF_REG_MEM_STORE, bb, insn, flags);
DF_REF_REG_MEM_STORE, bb, insn, flags, width, offset);
break;
case STRICT_LOW_PART:
{
@ -2902,20 +3001,31 @@ df_uses_record (struct df_collection_rec *collection_rec,
df_uses_record (collection_rec,
(GET_CODE (dst) == SUBREG) ? &SUBREG_REG (dst) : temp,
DF_REF_REG_USE, bb, insn,
DF_REF_READ_WRITE | DF_REF_STRICT_LOWER_PART);
DF_REF_READ_WRITE | DF_REF_STRICT_LOW_PART, width, offset);
}
break;
case ZERO_EXTRACT:
case SIGN_EXTRACT:
df_uses_record (collection_rec, &XEXP (dst, 0),
DF_REF_REG_USE, bb, insn,
DF_REF_READ_WRITE | DF_REF_EXTRACT);
df_uses_record (collection_rec, &XEXP (dst, 1),
DF_REF_REG_USE, bb, insn, flags);
df_uses_record (collection_rec, &XEXP (dst, 2),
DF_REF_REG_USE, bb, insn, flags);
dst = XEXP (dst, 0);
{
if (GET_CODE (XEXP (dst, 1)) == CONST_INT
&& GET_CODE (XEXP (dst, 2)) == CONST_INT)
{
width = INTVAL (XEXP (dst, 1));
offset = INTVAL (XEXP (dst, 2));
}
else
{
df_uses_record (collection_rec, &XEXP (dst, 1),
DF_REF_REG_USE, bb, insn, flags, width, offset);
df_uses_record (collection_rec, &XEXP (dst, 2),
DF_REF_REG_USE, bb, insn, flags, width, offset);
}
df_uses_record (collection_rec, &XEXP (dst, 0),
DF_REF_REG_USE, bb, insn,
DF_REF_READ_WRITE | DF_REF_ZERO_EXTRACT, width, offset);
}
break;
default:
gcc_unreachable ();
}
@ -2962,7 +3072,7 @@ df_uses_record (struct df_collection_rec *collection_rec,
for (j = 0; j < ASM_OPERANDS_INPUT_LENGTH (x); j++)
df_uses_record (collection_rec, &ASM_OPERANDS_INPUT (x, j),
DF_REF_REG_USE, bb, insn, flags);
DF_REF_REG_USE, bb, insn, flags, width, offset);
return;
}
break;
@ -2977,7 +3087,7 @@ df_uses_record (struct df_collection_rec *collection_rec,
/* Catch the def of the register being modified. */
df_ref_record (collection_rec, XEXP (x, 0), &XEXP (x, 0), bb, insn,
DF_REF_REG_DEF,
flags | DF_REF_READ_WRITE | DF_REF_PRE_POST_MODIFY);
flags | DF_REF_READ_WRITE | DF_REF_PRE_POST_MODIFY, width, offset);
/* ... Fall through to handle uses ... */
@ -3000,14 +3110,16 @@ df_uses_record (struct df_collection_rec *collection_rec,
loc = &XEXP (x, 0);
goto retry;
}
df_uses_record (collection_rec, &XEXP (x, i), ref_type, bb, insn, flags);
df_uses_record (collection_rec, &XEXP (x, i), ref_type,
bb, insn, flags, width, offset);
}
else if (fmt[i] == 'E')
{
int j;
for (j = 0; j < XVECLEN (x, i); j++)
df_uses_record (collection_rec,
&XVECEXP (x, i, j), ref_type, bb, insn, flags);
&XVECEXP (x, i, j), ref_type,
bb, insn, flags, width, offset);
}
}
}
@ -3027,11 +3139,21 @@ df_get_conditional_uses (struct df_collection_rec *collection_rec)
struct df_ref *ref = collection_rec->def_vec[i];
if (DF_REF_FLAGS_IS_SET (ref, DF_REF_CONDITIONAL))
{
struct df_ref *use
= df_ref_create_structure (collection_rec, DF_REF_REG (ref),
DF_REF_LOC (ref), DF_REF_BB (ref),
DF_REF_INSN (ref), DF_REF_REG_USE,
DF_REF_FLAGS (ref) & ~DF_REF_CONDITIONAL);
int width = -1;
int offset = -1;
struct df_ref *use;
if (DF_REF_FLAGS_IS_SET (ref, DF_REF_SIGN_EXTRACT | DF_REF_ZERO_EXTRACT))
{
width = DF_REF_WIDTH (ref);
offset = DF_REF_OFFSET (ref);
}
use = df_ref_create_structure (collection_rec, DF_REF_REG (ref),
DF_REF_LOC (ref), DF_REF_BB (ref),
DF_REF_INSN (ref), DF_REF_REG_USE,
DF_REF_FLAGS (ref) & ~DF_REF_CONDITIONAL,
width, offset);
DF_REF_REGNO (use) = DF_REF_REGNO (ref);
}
}
@ -3069,7 +3191,7 @@ df_get_call_refs (struct df_collection_rec * collection_rec,
{
if (GET_CODE (XEXP (note, 0)) == USE)
df_uses_record (collection_rec, &XEXP (XEXP (note, 0), 0),
DF_REF_REG_USE, bb, insn, flags);
DF_REF_REG_USE, bb, insn, flags, -1, -1);
else if (GET_CODE (XEXP (note, 0)) == CLOBBER)
{
if (REG_P (XEXP (XEXP (note, 0), 0)))
@ -3081,13 +3203,13 @@ df_get_call_refs (struct df_collection_rec * collection_rec,
}
else
df_uses_record (collection_rec, &XEXP (note, 0),
DF_REF_REG_USE, bb, insn, flags);
DF_REF_REG_USE, bb, insn, flags, -1, -1);
}
}
/* The stack ptr is used (honorarily) by a CALL insn. */
df_ref_record (collection_rec, regno_reg_rtx[STACK_POINTER_REGNUM],
NULL, bb, insn, DF_REF_REG_USE, DF_REF_CALL_STACK_USAGE | flags);
NULL, bb, insn, DF_REF_REG_USE, DF_REF_CALL_STACK_USAGE | flags, -1, -1);
/* Calls may also reference any of the global registers,
so they are recorded as used. */
@ -3095,9 +3217,9 @@ df_get_call_refs (struct df_collection_rec * collection_rec,
if (global_regs[i])
{
df_ref_record (collection_rec, regno_reg_rtx[i],
NULL, bb, insn, DF_REF_REG_USE, flags);
NULL, bb, insn, DF_REF_REG_USE, flags, -1, -1);
df_ref_record (collection_rec, regno_reg_rtx[i],
NULL, bb, insn, DF_REF_REG_DEF, flags);
NULL, bb, insn, DF_REF_REG_DEF, flags, -1, -1);
}
is_sibling_call = SIBLING_CALL_P (insn);
@ -3110,7 +3232,7 @@ df_get_call_refs (struct df_collection_rec * collection_rec,
|| refers_to_regno_p (ui, ui+1,
current_function_return_rtx, NULL)))
df_ref_record (collection_rec, regno_reg_rtx[ui],
NULL, bb, insn, DF_REF_REG_DEF, DF_REF_MAY_CLOBBER | flags);
NULL, bb, insn, DF_REF_REG_DEF, DF_REF_MAY_CLOBBER | flags, -1, -1);
}
BITMAP_FREE (defs_generated);
@ -3148,7 +3270,7 @@ df_insn_refs_collect (struct df_collection_rec* collection_rec,
case REG_EQUAL:
df_uses_record (collection_rec,
&XEXP (note, 0), DF_REF_REG_USE,
bb, insn, DF_REF_IN_NOTE);
bb, insn, DF_REF_IN_NOTE, -1, -1);
break;
case REG_NON_LOCAL_GOTO:
/* The frame ptr is used by a non-local goto. */
@ -3156,13 +3278,13 @@ df_insn_refs_collect (struct df_collection_rec* collection_rec,
regno_reg_rtx[FRAME_POINTER_REGNUM],
NULL,
bb, insn,
DF_REF_REG_USE, 0);
DF_REF_REG_USE, 0, -1, -1);
#if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
df_ref_record (collection_rec,
regno_reg_rtx[HARD_FRAME_POINTER_REGNUM],
NULL,
bb, insn,
DF_REF_REG_USE, 0);
DF_REF_REG_USE, 0, -1, -1);
#endif
break;
default:
@ -3176,7 +3298,7 @@ df_insn_refs_collect (struct df_collection_rec* collection_rec,
/* Record the register uses. */
df_uses_record (collection_rec,
&PATTERN (insn), DF_REF_REG_USE, bb, insn, 0);
&PATTERN (insn), DF_REF_REG_USE, bb, insn, 0, -1, -1);
/* DF_REF_CONDITIONAL needs corresponding USES. */
if (is_cond_exec)
@ -3259,7 +3381,7 @@ df_bb_refs_collect (struct df_collection_rec *collection_rec, basic_block bb)
if (regno == INVALID_REGNUM)
break;
df_ref_record (collection_rec, regno_reg_rtx[regno], NULL,
bb, NULL, DF_REF_REG_DEF, DF_REF_AT_TOP);
bb, NULL, DF_REF_REG_DEF, DF_REF_AT_TOP, -1, -1);
}
}
#endif
@ -3283,7 +3405,7 @@ df_bb_refs_collect (struct df_collection_rec *collection_rec, basic_block bb)
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
if (EH_USES (i))
df_ref_record (collection_rec, regno_reg_rtx[i], NULL,
bb, NULL, DF_REF_REG_USE, DF_REF_AT_TOP);
bb, NULL, DF_REF_REG_USE, DF_REF_AT_TOP, -1, -1);
}
#endif
@ -3291,7 +3413,7 @@ df_bb_refs_collect (struct df_collection_rec *collection_rec, basic_block bb)
non-local goto. */
if (bb->flags & BB_NON_LOCAL_GOTO_TARGET)
df_ref_record (collection_rec, hard_frame_pointer_rtx, NULL,
bb, NULL, DF_REF_REG_DEF, DF_REF_AT_TOP);
bb, NULL, DF_REF_REG_DEF, DF_REF_AT_TOP, -1, -1);
/* Add the artificial uses. */
if (bb->index >= NUM_FIXED_BLOCKS)
@ -3305,7 +3427,7 @@ df_bb_refs_collect (struct df_collection_rec *collection_rec, basic_block bb)
EXECUTE_IF_SET_IN_BITMAP (au, 0, regno, bi)
{
df_ref_record (collection_rec, regno_reg_rtx[regno], NULL,
bb, NULL, DF_REF_REG_USE, 0);
bb, NULL, DF_REF_REG_USE, 0, -1, -1);
}
}
@ -3598,7 +3720,7 @@ df_entry_block_defs_collect (struct df_collection_rec *collection_rec,
EXECUTE_IF_SET_IN_BITMAP (entry_block_defs, 0, i, bi)
{
df_ref_record (collection_rec, regno_reg_rtx[i], NULL,
ENTRY_BLOCK_PTR, NULL, DF_REF_REG_DEF, 0);
ENTRY_BLOCK_PTR, NULL, DF_REF_REG_DEF, 0, -1, -1);
}
df_canonize_collection_rec (collection_rec);
@ -3759,7 +3881,7 @@ df_exit_block_uses_collect (struct df_collection_rec *collection_rec, bitmap exi
EXECUTE_IF_SET_IN_BITMAP (exit_block_uses, 0, i, bi)
df_ref_record (collection_rec, regno_reg_rtx[i], NULL,
EXIT_BLOCK_PTR, NULL, DF_REF_REG_USE, 0);
EXIT_BLOCK_PTR, NULL, DF_REF_REG_USE, 0, -1, -1);
#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
/* It is deliberate that this is not put in the exit block uses but
@ -3769,7 +3891,7 @@ df_exit_block_uses_collect (struct df_collection_rec *collection_rec, bitmap exi
&& bb_has_eh_pred (EXIT_BLOCK_PTR)
&& fixed_regs[ARG_POINTER_REGNUM])
df_ref_record (collection_rec, regno_reg_rtx[ARG_POINTER_REGNUM], NULL,
EXIT_BLOCK_PTR, NULL, DF_REF_REG_USE, 0);
EXIT_BLOCK_PTR, NULL, DF_REF_REG_USE, 0, -1, -1);
#endif
df_canonize_collection_rec (collection_rec);

View File

@ -117,14 +117,18 @@ enum df_ref_flags
DF_REF_MUST_CLOBBER = 1 << 7,
/* This flag is set if this ref is inside a pre/post modify. */
DF_REF_PRE_POST_MODIFY = 1 << 8,
/* If the ref has one of the following two flags set, then the
struct df_ref can be cast to struct df_ref_extract to access
the width and offset fields. */
/* This flag is set if the ref contains a SIGN_EXTRACT. */
DF_REF_SIGN_EXTRACT = 1 << 8,
/* This flag is set if the ref contains a ZERO_EXTRACT or SIGN_EXTRACT. */
DF_REF_EXTRACT = 1 << 9,
/* This flag is set if the ref contains a ZERO_EXTRACT. */
DF_REF_ZERO_EXTRACT = 1 << 9,
/* This flag is set if the ref contains a STRICT_LOWER_PART. */
DF_REF_STRICT_LOWER_PART = 1 << 10,
/* This flag is set if the ref contains a STRICT_LOW_PART. */
DF_REF_STRICT_LOW_PART = 1 << 10,
/* This flag is set if the ref contains a SUBREG. */
DF_REF_SUBREG = 1 << 11,
@ -138,7 +142,11 @@ enum df_ref_flags
DF_REF_CALL_STACK_USAGE = 1 << 13,
/* This flag is used for verification of existing refs. */
DF_REF_REG_MARKER = 1 << 14
DF_REF_REG_MARKER = 1 << 14,
/* This flag is set if this ref is inside a pre/post modify. */
DF_REF_PRE_POST_MODIFY = 1 << 15
};
/* The possible ordering of refs within the df_ref_info. */
@ -381,6 +389,17 @@ struct df_ref
struct df_ref *prev_reg; /* Prev ref with same regno and type. */
};
/* A df_ref_extract is just a df_ref with a width and offset field at
the end of it. It is used to hold this information if the ref was
wrapped by a SIGN_EXTRACT or a ZERO_EXTRACT and to pass this info
to passes that wish to process partial regs precisely. */
struct df_ref_extract
{
struct df_ref ref;
int width;
int offset;
};
/* These links are used for two purposes:
1) def-use or use-def chains.
2) Multiword hard registers that underly a single hardware register. */
@ -598,7 +617,10 @@ struct df
#define DF_REF_IS_REG_MARKED(REF) (DF_REF_FLAGS_IS_SET ((REF),DF_REF_REG_MARKER))
#define DF_REF_NEXT_REG(REF) ((REF)->next_reg)
#define DF_REF_PREV_REG(REF) ((REF)->prev_reg)
/* The following two macros may only be applied if one of
DF_REF_SIGN_EXTRACT | DF_REF_ZERO_EXTRACT is true. */
#define DF_REF_WIDTH(REF) (((struct df_ref_extract *)(REF))->width)
#define DF_REF_OFFSET(REF) (((struct df_ref_extract *)(REF))->offset)
/* Macros to determine the reference type. */
#define DF_REF_REG_DEF_P(REF) (DF_REF_TYPE (REF) == DF_REF_REG_DEF)
@ -862,7 +884,8 @@ extern void df_grow_reg_info (void);
extern void df_grow_insn_info (void);
extern void df_scan_blocks (void);
extern struct df_ref *df_ref_create (rtx, rtx *, rtx,basic_block,
enum df_ref_type, enum df_ref_flags);
enum df_ref_type, enum df_ref_flags,
int, int);
extern void df_ref_remove (struct df_ref *);
extern struct df_insn_info * df_insn_create_insn_record (rtx);
extern void df_insn_delete (basic_block, unsigned int);

View File

@ -642,17 +642,25 @@ update_df (rtx insn, rtx *loc, struct df_ref **use_rec, enum df_ref_type type,
{
struct df_ref *use = *use_rec;
struct df_ref *orig_use = use, *new_use;
int width = -1;
int offset = -1;
rtx *new_loc = find_occurrence (loc, DF_REF_REG (orig_use));
use_rec++;
if (!new_loc)
continue;
if (DF_REF_FLAGS_IS_SET (orig_use, DF_REF_SIGN_EXTRACT | DF_REF_ZERO_EXTRACT))
{
width = DF_REF_WIDTH (orig_use);
offset = DF_REF_OFFSET (orig_use);
}
/* Add a new insn use. Use the original type, because it says if the
use was within a MEM. */
new_use = df_ref_create (DF_REF_REG (orig_use), new_loc,
insn, BLOCK_FOR_INSN (insn),
type, DF_REF_FLAGS (orig_use) | new_flags);
type, DF_REF_FLAGS (orig_use) | new_flags, width, offset);
/* Set up the use-def chain. */
df_chain_copy (new_use, DF_REF_CHAIN (orig_use));

View File

@ -1490,7 +1490,7 @@ build_insn_chain (void)
/* We can model subregs, but not if they are
wrapped in ZERO_EXTRACTS. */
if (GET_CODE (reg) == SUBREG
&& !DF_REF_FLAGS_IS_SET (def, DF_REF_EXTRACT))
&& !DF_REF_FLAGS_IS_SET (def, DF_REF_ZERO_EXTRACT))
{
unsigned int start = SUBREG_BYTE (reg);
unsigned int last = start
@ -1503,7 +1503,7 @@ build_insn_chain (void)
regno, reg);
if (!DF_REF_FLAGS_IS_SET
(def, DF_REF_STRICT_LOWER_PART))
(def, DF_REF_STRICT_LOW_PART))
{
/* Expand the range to cover entire words.
Bytes added here are "don't care". */
@ -1566,7 +1566,7 @@ build_insn_chain (void)
precisely so we do not need to look at the
fabricated use. */
if (DF_REF_FLAGS_IS_SET (use, DF_REF_READ_WRITE)
&& !DF_REF_FLAGS_IS_SET (use, DF_REF_EXTRACT)
&& !DF_REF_FLAGS_IS_SET (use, DF_REF_ZERO_EXTRACT)
&& DF_REF_FLAGS_IS_SET (use, DF_REF_SUBREG))
continue;
@ -1585,7 +1585,8 @@ build_insn_chain (void)
if (regno < FIRST_PSEUDO_REGISTER || reg_renumber[regno] >= 0)
{
if (GET_CODE (reg) == SUBREG
&& !DF_REF_FLAGS_IS_SET (use, DF_REF_EXTRACT))
&& !DF_REF_FLAGS_IS_SET (use,
DF_REF_SIGN_EXTRACT | DF_REF_ZERO_EXTRACT))
{
unsigned int start = SUBREG_BYTE (reg);
unsigned int last = start

View File

@ -297,7 +297,7 @@ mark_reg_store (sparseset allocnos_live,
{
unsigned int start = regno;
unsigned int last = end_hard_regno (mode, regno);
if ((GET_CODE (reg) == SUBREG) && !DF_REF_FLAGS_IS_SET (ref, DF_REF_EXTRACT))
if ((GET_CODE (reg) == SUBREG) && !DF_REF_FLAGS_IS_SET (ref, DF_REF_ZERO_EXTRACT))
{
start += subreg_regno_offset (regno, GET_MODE (SUBREG_REG (reg)),
SUBREG_BYTE (reg), GET_MODE (reg));
@ -457,7 +457,7 @@ clear_reg_in_live (sparseset allocnos_live,
if (allocnum >= 0)
{
if (GET_CODE (reg) == SUBREG
&& !DF_REF_FLAGS_IS_SET (def, DF_REF_EXTRACT))
&& !DF_REF_FLAGS_IS_SET (def, DF_REF_ZERO_EXTRACT))
{
unsigned int start = SUBREG_BYTE (reg);
unsigned int last = start + GET_MODE_SIZE (GET_MODE (reg));
@ -465,7 +465,7 @@ clear_reg_in_live (sparseset allocnos_live,
ra_init_live_subregs (sparseset_bit_p (allocnos_live, allocnum),
live_subregs, live_subregs_used, allocnum, reg);
if (!DF_REF_FLAGS_IS_SET (def, DF_REF_STRICT_LOWER_PART))
if (!DF_REF_FLAGS_IS_SET (def, DF_REF_STRICT_LOW_PART))
{
/* Expand the range to cover entire words.
Bytes added here are "don't care". */
@ -511,7 +511,7 @@ clear_reg_in_live (sparseset allocnos_live,
{
unsigned int start = regno;
if (GET_CODE (reg) == SUBREG
&& !DF_REF_FLAGS_IS_SET (def, DF_REF_EXTRACT))
&& !DF_REF_FLAGS_IS_SET (def, DF_REF_ZERO_EXTRACT))
{
unsigned int last;
start += SUBREG_BYTE (reg);
@ -864,7 +864,7 @@ global_conflicts (void)
rtx reg = DF_REF_REG (def);
set_reg_in_live (allocnos_live, live_subregs, live_subregs_used,
&hard_regs_live, reg,
DF_REF_FLAGS_IS_SET (def, DF_REF_EXTRACT));
DF_REF_FLAGS_IS_SET (def, DF_REF_ZERO_EXTRACT));
if (dump_file)
dump_ref (dump_file, " adding def", "\n",
reg, DF_REF_REGNO (def), live_subregs, live_subregs_used);
@ -946,7 +946,7 @@ global_conflicts (void)
use unless that set also happens to wrapped in a
ZERO_EXTRACT. */
if (DF_REF_FLAGS_IS_SET (use, DF_REF_READ_WRITE)
&& (!DF_REF_FLAGS_IS_SET (use, DF_REF_EXTRACT))
&& (!DF_REF_FLAGS_IS_SET (use, DF_REF_ZERO_EXTRACT))
&& DF_REF_FLAGS_IS_SET (use, DF_REF_SUBREG))
continue;
@ -957,7 +957,7 @@ global_conflicts (void)
if (allocnum >= 0)
{
if (GET_CODE (reg) == SUBREG
&& !DF_REF_FLAGS_IS_SET (use, DF_REF_EXTRACT))
&& !DF_REF_FLAGS_IS_SET (use, DF_REF_ZERO_EXTRACT))
{
unsigned int start = SUBREG_BYTE (reg);
unsigned int last = start + GET_MODE_SIZE (GET_MODE (reg));