loop-unroll.c (struct iv_to_split): Add pointer to next.
* loop-unroll.c (struct iv_to_split): Add pointer to next. (struct var_to_expand): Likewise. (struct opt_info): Add head and tail for linked lists of the above. (analyze_insn_to_expand_var): Initialize next. (analyze_iv_to_split_insn): Likewise. (analyze_insns_in_loop): Create linked lists. (allocate_basic_variable): Simplify for use without hash table. (insert_var_expansion_initialization): Likewise, make it type-safer. (combine_var_copies_in_loop_exit): Likewise. (apply_opt_in_copies): Walk lists rather than hash tables. (release_var_copies): Simplified and inlined by hand into... (free_opt_info): ... this function. From-SVN: r148090
This commit is contained in:
parent
4ea08463a7
commit
a9f6eceee7
@ -1,3 +1,18 @@
|
|||||||
|
2009-06-02 Alexandre Oliva <aoliva@redhat.com>
|
||||||
|
|
||||||
|
* loop-unroll.c (struct iv_to_split): Add pointer to next.
|
||||||
|
(struct var_to_expand): Likewise.
|
||||||
|
(struct opt_info): Add head and tail for linked lists of the above.
|
||||||
|
(analyze_insn_to_expand_var): Initialize next.
|
||||||
|
(analyze_iv_to_split_insn): Likewise.
|
||||||
|
(analyze_insns_in_loop): Create linked lists.
|
||||||
|
(allocate_basic_variable): Simplify for use without hash table.
|
||||||
|
(insert_var_expansion_initialization): Likewise, make it type-safer.
|
||||||
|
(combine_var_copies_in_loop_exit): Likewise.
|
||||||
|
(apply_opt_in_copies): Walk lists rather than hash tables.
|
||||||
|
(release_var_copies): Simplified and inlined by hand into...
|
||||||
|
(free_opt_info): ... this function.
|
||||||
|
|
||||||
2009-06-02 Richard Guenther <rguenther@suse.de>
|
2009-06-02 Richard Guenther <rguenther@suse.de>
|
||||||
|
|
||||||
* tree-ssa-sccvn.c (copy_reference_ops_from_ref): Use DECL_SIZE
|
* tree-ssa-sccvn.c (copy_reference_ops_from_ref): Use DECL_SIZE
|
||||||
|
@ -77,6 +77,7 @@ struct iv_to_split
|
|||||||
rtx base_var; /* The variable on that the values in the further
|
rtx base_var; /* The variable on that the values in the further
|
||||||
iterations are based. */
|
iterations are based. */
|
||||||
rtx step; /* Step of the induction variable. */
|
rtx step; /* Step of the induction variable. */
|
||||||
|
struct iv_to_split *next; /* Next entry in walking order. */
|
||||||
unsigned n_loc;
|
unsigned n_loc;
|
||||||
unsigned loc[3]; /* Location where the definition of the induction
|
unsigned loc[3]; /* Location where the definition of the induction
|
||||||
variable occurs in the insn. For example if
|
variable occurs in the insn. For example if
|
||||||
@ -91,6 +92,7 @@ struct var_to_expand
|
|||||||
rtx insn; /* The insn in that the variable expansion occurs. */
|
rtx insn; /* The insn in that the variable expansion occurs. */
|
||||||
rtx reg; /* The accumulator which is expanded. */
|
rtx reg; /* The accumulator which is expanded. */
|
||||||
VEC(rtx,heap) *var_expansions; /* The copies of the accumulator which is expanded. */
|
VEC(rtx,heap) *var_expansions; /* The copies of the accumulator which is expanded. */
|
||||||
|
struct var_to_expand *next; /* Next entry in walking order. */
|
||||||
enum rtx_code op; /* The type of the accumulation - addition, subtraction
|
enum rtx_code op; /* The type of the accumulation - addition, subtraction
|
||||||
or multiplication. */
|
or multiplication. */
|
||||||
int expansion_count; /* Count the number of expansions generated so far. */
|
int expansion_count; /* Count the number of expansions generated so far. */
|
||||||
@ -110,8 +112,12 @@ struct var_to_expand
|
|||||||
struct opt_info
|
struct opt_info
|
||||||
{
|
{
|
||||||
htab_t insns_to_split; /* A hashtable of insns to split. */
|
htab_t insns_to_split; /* A hashtable of insns to split. */
|
||||||
|
struct iv_to_split *iv_to_split_head; /* The first iv to split. */
|
||||||
|
struct iv_to_split **iv_to_split_tail; /* Pointer to the tail of the list. */
|
||||||
htab_t insns_with_var_to_expand; /* A hashtable of insns with accumulators
|
htab_t insns_with_var_to_expand; /* A hashtable of insns with accumulators
|
||||||
to expand. */
|
to expand. */
|
||||||
|
struct var_to_expand *var_to_expand_head; /* The first var to expand. */
|
||||||
|
struct var_to_expand **var_to_expand_tail; /* Pointer to the tail of the list. */
|
||||||
unsigned first_new_block; /* The first basic block that was
|
unsigned first_new_block; /* The first basic block that was
|
||||||
duplicated. */
|
duplicated. */
|
||||||
basic_block loop_exit; /* The loop exit basic block. */
|
basic_block loop_exit; /* The loop exit basic block. */
|
||||||
@ -139,9 +145,10 @@ static struct var_to_expand *analyze_insn_to_expand_var (struct loop*, rtx);
|
|||||||
static bool referenced_in_one_insn_in_loop_p (struct loop *, rtx);
|
static bool referenced_in_one_insn_in_loop_p (struct loop *, rtx);
|
||||||
static struct iv_to_split *analyze_iv_to_split_insn (rtx);
|
static struct iv_to_split *analyze_iv_to_split_insn (rtx);
|
||||||
static void expand_var_during_unrolling (struct var_to_expand *, rtx);
|
static void expand_var_during_unrolling (struct var_to_expand *, rtx);
|
||||||
static int insert_var_expansion_initialization (void **, void *);
|
static void insert_var_expansion_initialization (struct var_to_expand *,
|
||||||
static int combine_var_copies_in_loop_exit (void **, void *);
|
basic_block);
|
||||||
static int release_var_copies (void **, void *);
|
static void combine_var_copies_in_loop_exit (struct var_to_expand *,
|
||||||
|
basic_block);
|
||||||
static rtx get_expansion (struct var_to_expand *);
|
static rtx get_expansion (struct var_to_expand *);
|
||||||
|
|
||||||
/* Unroll and/or peel (depending on FLAGS) LOOPS. */
|
/* Unroll and/or peel (depending on FLAGS) LOOPS. */
|
||||||
@ -1646,8 +1653,9 @@ analyze_insn_to_expand_var (struct loop *loop, rtx insn)
|
|||||||
/* Record the accumulator to expand. */
|
/* Record the accumulator to expand. */
|
||||||
ves = XNEW (struct var_to_expand);
|
ves = XNEW (struct var_to_expand);
|
||||||
ves->insn = insn;
|
ves->insn = insn;
|
||||||
ves->var_expansions = VEC_alloc (rtx, heap, 1);
|
|
||||||
ves->reg = copy_rtx (dest);
|
ves->reg = copy_rtx (dest);
|
||||||
|
ves->var_expansions = VEC_alloc (rtx, heap, 1);
|
||||||
|
ves->next = NULL;
|
||||||
ves->op = GET_CODE (src);
|
ves->op = GET_CODE (src);
|
||||||
ves->expansion_count = 0;
|
ves->expansion_count = 0;
|
||||||
ves->reuse_expansion = 0;
|
ves->reuse_expansion = 0;
|
||||||
@ -1723,6 +1731,7 @@ analyze_iv_to_split_insn (rtx insn)
|
|||||||
ivts->insn = insn;
|
ivts->insn = insn;
|
||||||
ivts->base_var = NULL_RTX;
|
ivts->base_var = NULL_RTX;
|
||||||
ivts->step = iv.step;
|
ivts->step = iv.step;
|
||||||
|
ivts->next = NULL;
|
||||||
ivts->n_loc = 1;
|
ivts->n_loc = 1;
|
||||||
ivts->loc[0] = 1;
|
ivts->loc[0] = 1;
|
||||||
|
|
||||||
@ -1754,8 +1763,12 @@ analyze_insns_in_loop (struct loop *loop)
|
|||||||
body = get_loop_body (loop);
|
body = get_loop_body (loop);
|
||||||
|
|
||||||
if (flag_split_ivs_in_unroller)
|
if (flag_split_ivs_in_unroller)
|
||||||
opt_info->insns_to_split = htab_create (5 * loop->num_nodes,
|
{
|
||||||
si_info_hash, si_info_eq, free);
|
opt_info->insns_to_split = htab_create (5 * loop->num_nodes,
|
||||||
|
si_info_hash, si_info_eq, free);
|
||||||
|
opt_info->iv_to_split_head = NULL;
|
||||||
|
opt_info->iv_to_split_tail = &opt_info->iv_to_split_head;
|
||||||
|
}
|
||||||
|
|
||||||
/* Record the loop exit bb and loop preheader before the unrolling. */
|
/* Record the loop exit bb and loop preheader before the unrolling. */
|
||||||
opt_info->loop_preheader = loop_preheader_edge (loop)->src;
|
opt_info->loop_preheader = loop_preheader_edge (loop)->src;
|
||||||
@ -1772,8 +1785,13 @@ analyze_insns_in_loop (struct loop *loop)
|
|||||||
|
|
||||||
if (flag_variable_expansion_in_unroller
|
if (flag_variable_expansion_in_unroller
|
||||||
&& can_apply)
|
&& can_apply)
|
||||||
opt_info->insns_with_var_to_expand = htab_create (5 * loop->num_nodes,
|
{
|
||||||
ve_info_hash, ve_info_eq, free);
|
opt_info->insns_with_var_to_expand = htab_create (5 * loop->num_nodes,
|
||||||
|
ve_info_hash,
|
||||||
|
ve_info_eq, free);
|
||||||
|
opt_info->var_to_expand_head = NULL;
|
||||||
|
opt_info->var_to_expand_tail = &opt_info->var_to_expand_head;
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < loop->num_nodes; i++)
|
for (i = 0; i < loop->num_nodes; i++)
|
||||||
{
|
{
|
||||||
@ -1792,7 +1810,10 @@ analyze_insns_in_loop (struct loop *loop)
|
|||||||
if (ivts)
|
if (ivts)
|
||||||
{
|
{
|
||||||
slot1 = htab_find_slot (opt_info->insns_to_split, ivts, INSERT);
|
slot1 = htab_find_slot (opt_info->insns_to_split, ivts, INSERT);
|
||||||
|
gcc_assert (*slot1 == NULL);
|
||||||
*slot1 = ivts;
|
*slot1 = ivts;
|
||||||
|
*opt_info->iv_to_split_tail = ivts;
|
||||||
|
opt_info->iv_to_split_tail = &ivts->next;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1802,7 +1823,10 @@ analyze_insns_in_loop (struct loop *loop)
|
|||||||
if (ves)
|
if (ves)
|
||||||
{
|
{
|
||||||
slot2 = htab_find_slot (opt_info->insns_with_var_to_expand, ves, INSERT);
|
slot2 = htab_find_slot (opt_info->insns_with_var_to_expand, ves, INSERT);
|
||||||
|
gcc_assert (*slot2 == NULL);
|
||||||
*slot2 = ves;
|
*slot2 = ves;
|
||||||
|
*opt_info->var_to_expand_tail = ves;
|
||||||
|
opt_info->var_to_expand_tail = &ves->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1862,18 +1886,14 @@ get_ivts_expr (rtx expr, struct iv_to_split *ivts)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate basic variable for the induction variable chain. Callback for
|
/* Allocate basic variable for the induction variable chain. */
|
||||||
htab_traverse. */
|
|
||||||
|
|
||||||
static int
|
static void
|
||||||
allocate_basic_variable (void **slot, void *data ATTRIBUTE_UNUSED)
|
allocate_basic_variable (struct iv_to_split *ivts)
|
||||||
{
|
{
|
||||||
struct iv_to_split *ivts = (struct iv_to_split *) *slot;
|
|
||||||
rtx expr = *get_ivts_expr (single_set (ivts->insn), ivts);
|
rtx expr = *get_ivts_expr (single_set (ivts->insn), ivts);
|
||||||
|
|
||||||
ivts->base_var = gen_reg_rtx (GET_MODE (expr));
|
ivts->base_var = gen_reg_rtx (GET_MODE (expr));
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Insert initialization of basic variable of IVTS before INSN, taking
|
/* Insert initialization of basic variable of IVTS before INSN, taking
|
||||||
@ -2010,14 +2030,13 @@ expand_var_during_unrolling (struct var_to_expand *ve, rtx insn)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize the variable expansions in loop preheader.
|
/* Initialize the variable expansions in loop preheader. PLACE is the
|
||||||
Callbacks for htab_traverse. PLACE_P is the loop-preheader
|
loop-preheader basic block where the initialization of the
|
||||||
basic block where the initialization of the expansions
|
expansions should take place. The expansions are initialized with
|
||||||
should take place. The expansions are initialized with (-0)
|
(-0) when the operation is plus or minus to honor sign zero. This
|
||||||
when the operation is plus or minus to honor sign zero.
|
way we can prevent cases where the sign of the final result is
|
||||||
This way we can prevent cases where the sign of the final result is
|
effected by the sign of the expansion. Here is an example to
|
||||||
effected by the sign of the expansion.
|
demonstrate this:
|
||||||
Here is an example to demonstrate this:
|
|
||||||
|
|
||||||
for (i = 0 ; i < n; i++)
|
for (i = 0 ; i < n; i++)
|
||||||
sum += something;
|
sum += something;
|
||||||
@ -2038,18 +2057,17 @@ expand_var_during_unrolling (struct var_to_expand *ve, rtx insn)
|
|||||||
should be initialized with -zero as well (otherwise we will get +zero
|
should be initialized with -zero as well (otherwise we will get +zero
|
||||||
as the final result). */
|
as the final result). */
|
||||||
|
|
||||||
static int
|
static void
|
||||||
insert_var_expansion_initialization (void **slot, void *place_p)
|
insert_var_expansion_initialization (struct var_to_expand *ve,
|
||||||
|
basic_block place)
|
||||||
{
|
{
|
||||||
struct var_to_expand *ve = (struct var_to_expand *) *slot;
|
|
||||||
basic_block place = (basic_block)place_p;
|
|
||||||
rtx seq, var, zero_init, insn;
|
rtx seq, var, zero_init, insn;
|
||||||
unsigned i;
|
unsigned i;
|
||||||
enum machine_mode mode = GET_MODE (ve->reg);
|
enum machine_mode mode = GET_MODE (ve->reg);
|
||||||
bool honor_signed_zero_p = HONOR_SIGNED_ZEROS (mode);
|
bool honor_signed_zero_p = HONOR_SIGNED_ZEROS (mode);
|
||||||
|
|
||||||
if (VEC_length (rtx, ve->var_expansions) == 0)
|
if (VEC_length (rtx, ve->var_expansions) == 0)
|
||||||
return 1;
|
return;
|
||||||
|
|
||||||
start_sequence ();
|
start_sequence ();
|
||||||
if (ve->op == PLUS || ve->op == MINUS)
|
if (ve->op == PLUS || ve->op == MINUS)
|
||||||
@ -2077,26 +2095,21 @@ insert_var_expansion_initialization (void **slot, void *place_p)
|
|||||||
insn = NEXT_INSN (insn);
|
insn = NEXT_INSN (insn);
|
||||||
|
|
||||||
emit_insn_after (seq, insn);
|
emit_insn_after (seq, insn);
|
||||||
/* Continue traversing the hash table. */
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Combine the variable expansions at the loop exit.
|
/* Combine the variable expansions at the loop exit. PLACE is the
|
||||||
Callbacks for htab_traverse. PLACE_P is the loop exit
|
loop exit basic block where the summation of the expansions should
|
||||||
basic block where the summation of the expansions should
|
take place. */
|
||||||
take place. */
|
|
||||||
|
|
||||||
static int
|
static void
|
||||||
combine_var_copies_in_loop_exit (void **slot, void *place_p)
|
combine_var_copies_in_loop_exit (struct var_to_expand *ve, basic_block place)
|
||||||
{
|
{
|
||||||
struct var_to_expand *ve = (struct var_to_expand *) *slot;
|
|
||||||
basic_block place = (basic_block)place_p;
|
|
||||||
rtx sum = ve->reg;
|
rtx sum = ve->reg;
|
||||||
rtx expr, seq, var, insn;
|
rtx expr, seq, var, insn;
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
|
||||||
if (VEC_length (rtx, ve->var_expansions) == 0)
|
if (VEC_length (rtx, ve->var_expansions) == 0)
|
||||||
return 1;
|
return;
|
||||||
|
|
||||||
start_sequence ();
|
start_sequence ();
|
||||||
if (ve->op == PLUS || ve->op == MINUS)
|
if (ve->op == PLUS || ve->op == MINUS)
|
||||||
@ -2123,9 +2136,6 @@ combine_var_copies_in_loop_exit (void **slot, void *place_p)
|
|||||||
insn = NEXT_INSN (insn);
|
insn = NEXT_INSN (insn);
|
||||||
|
|
||||||
emit_insn_after (seq, insn);
|
emit_insn_after (seq, insn);
|
||||||
|
|
||||||
/* Continue traversing the hash table. */
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Apply loop optimizations in loop copies using the
|
/* Apply loop optimizations in loop copies using the
|
||||||
@ -2154,7 +2164,8 @@ apply_opt_in_copies (struct opt_info *opt_info,
|
|||||||
|
|
||||||
/* Allocate the basic variables (i0). */
|
/* Allocate the basic variables (i0). */
|
||||||
if (opt_info->insns_to_split)
|
if (opt_info->insns_to_split)
|
||||||
htab_traverse (opt_info->insns_to_split, allocate_basic_variable, NULL);
|
for (ivts = opt_info->iv_to_split_head; ivts; ivts = ivts->next)
|
||||||
|
allocate_basic_variable (ivts);
|
||||||
|
|
||||||
for (i = opt_info->first_new_block; i < (unsigned) last_basic_block; i++)
|
for (i = opt_info->first_new_block; i < (unsigned) last_basic_block; i++)
|
||||||
{
|
{
|
||||||
@ -2218,12 +2229,10 @@ apply_opt_in_copies (struct opt_info *opt_info,
|
|||||||
and take care of combining them at the loop exit. */
|
and take care of combining them at the loop exit. */
|
||||||
if (opt_info->insns_with_var_to_expand)
|
if (opt_info->insns_with_var_to_expand)
|
||||||
{
|
{
|
||||||
htab_traverse (opt_info->insns_with_var_to_expand,
|
for (ves = opt_info->var_to_expand_head; ves; ves = ves->next)
|
||||||
insert_var_expansion_initialization,
|
insert_var_expansion_initialization (ves, opt_info->loop_preheader);
|
||||||
opt_info->loop_preheader);
|
for (ves = opt_info->var_to_expand_head; ves; ves = ves->next)
|
||||||
htab_traverse (opt_info->insns_with_var_to_expand,
|
combine_var_copies_in_loop_exit (ves, opt_info->loop_exit);
|
||||||
combine_var_copies_in_loop_exit,
|
|
||||||
opt_info->loop_exit);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Rewrite also the original loop body. Find them as originals of the blocks
|
/* Rewrite also the original loop body. Find them as originals of the blocks
|
||||||
@ -2264,20 +2273,6 @@ apply_opt_in_copies (struct opt_info *opt_info,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Release the data structures used for the variable expansion
|
|
||||||
optimization. Callbacks for htab_traverse. */
|
|
||||||
|
|
||||||
static int
|
|
||||||
release_var_copies (void **slot, void *data ATTRIBUTE_UNUSED)
|
|
||||||
{
|
|
||||||
struct var_to_expand *ve = (struct var_to_expand *) *slot;
|
|
||||||
|
|
||||||
VEC_free (rtx, heap, ve->var_expansions);
|
|
||||||
|
|
||||||
/* Continue traversing the hash table. */
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Release OPT_INFO. */
|
/* Release OPT_INFO. */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -2287,8 +2282,10 @@ free_opt_info (struct opt_info *opt_info)
|
|||||||
htab_delete (opt_info->insns_to_split);
|
htab_delete (opt_info->insns_to_split);
|
||||||
if (opt_info->insns_with_var_to_expand)
|
if (opt_info->insns_with_var_to_expand)
|
||||||
{
|
{
|
||||||
htab_traverse (opt_info->insns_with_var_to_expand,
|
struct var_to_expand *ves;
|
||||||
release_var_copies, NULL);
|
|
||||||
|
for (ves = opt_info->var_to_expand_head; ves; ves = ves->next)
|
||||||
|
VEC_free (rtx, heap, ves->var_expansions);
|
||||||
htab_delete (opt_info->insns_with_var_to_expand);
|
htab_delete (opt_info->insns_with_var_to_expand);
|
||||||
}
|
}
|
||||||
free (opt_info);
|
free (opt_info);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user