patch to reduce register pressure from strength reduction
Joern Rennecke
amylaar@cygnus.co.uk
Fri Jan 29 16:32:00 GMT 1999
> Program received signal SIGSEGV, Segmentation fault.
> copy_loop_body (copy_start=0x82e40d4, copy_end=0x82e4144,
> map=0xbfff423c, exit_label=0x83304a8, last_iteration=0,
> unroll_type=UNROLL_MODULO,
> start_label=0x82e410c, loop_end=0x82e4e80, insert_before=0x82e4190,
> copy_notes_from=0x82e4190) at ../../egcs/gcc/unroll.c:1733
>
> Here's the code:
I have made a patch that allows me to compile your testcase.
I haven't analyzed the generated code, so please check it out.
Fri Jan 29 23:13:20 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
* loop.h (express_from): Declare.
(struct induction): Replace derived flag with derived_from pointer.
* loop.c (strength_reduce, record_giv, recombine_givs): Likewise.
(express_from): No longer static.
* unroll.c (find_splittable_givs): Replace derived with derived_from.
When processing an address giv with which another giv has been
combined that has also been derived from a third giv, handle like
having combined with the third giv.
Set splittable_regs_updates to 1 for derived givs.
Index: loop.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/loop.h,v
retrieving revision 1.16
diff -p -r1.16 loop.h
*** loop.h 1999/01/28 15:36:04 1.16
--- loop.h 1999/01/29 23:09:37
*************** struct induction
*** 101,108 ****
initialized in unrolled loop. */
unsigned shared : 1;
unsigned no_const_addval : 1; /* 1 if add_val does not contain a const. */
- unsigned derived : 1; /* For a giv, 1 if we decided to derive this
- giv from another one. */
int lifetime; /* Length of life of this giv */
rtx derive_adjustment; /* If nonzero, is an adjustment to be
subtracted from add_val when this giv
--- 101,106 ----
*************** struct induction
*** 115,120 ****
--- 113,120 ----
struct induction *same; /* If this giv has been combined with another
giv, this points to the base giv. The base
giv will have COMBINED_WITH non-zero. */
+ struct induction *derived_from;/* For a giv, if we decided to derive this
+ giv from another one. */
HOST_WIDE_INT const_adjust; /* Used by loop unrolling, when an address giv
is split, and a constant is eliminated from
the address, the -constant is stored here
*************** extern int first_increment_giv, last_inc
*** 226,231 ****
--- 226,232 ----
int invariant_p PROTO((rtx));
rtx get_condition_for_loop PROTO((rtx));
void emit_iv_add_mult PROTO((rtx, rtx, rtx, rtx, rtx));
+ rtx express_from PROTO((struct induction *, struct induction *));
/* Forward declarations for non-static functions declared in stmt.c. */
void find_loop_tree_blocks PROTO((void));
Index: loop.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/loop.c,v
retrieving revision 1.121
diff -p -r1.121 loop.c
*** loop.c 1999/01/29 14:36:59 1.121
--- loop.c 1999/01/29 23:09:40
*************** static int general_induction_var PROTO((
*** 320,326 ****
static int consec_sets_giv PROTO((int, rtx, rtx, rtx, rtx *, rtx *, rtx *));
static int check_dbra_loop PROTO((rtx, int, rtx, struct loop_info *));
static rtx express_from_1 PROTO((rtx, rtx, rtx));
- static rtx express_from PROTO((struct induction *, struct induction *));
static rtx combine_givs_p PROTO((struct induction *, struct induction *));
static void combine_givs PROTO((struct iv_class *));
struct recombine_givs_stats;
--- 320,325 ----
*************** strength_reduce (scan_start, end, loop_t
*** 4177,4183 ****
v->auto_inc_opt = 0;
v->unrolled = 0;
v->shared = 0;
! v->derived = 0;
v->always_computable = 1;
v->always_executed = 1;
v->replaceable = 1;
--- 4176,4182 ----
v->auto_inc_opt = 0;
v->unrolled = 0;
v->shared = 0;
! v->derived_from = 0;
v->always_computable = 1;
v->always_executed = 1;
v->replaceable = 1;
*************** strength_reduce (scan_start, end, loop_t
*** 4613,4619 ****
v->new_reg = gen_reg_rtx (v->mode);
! if (v->derived)
{
PATTERN (v->insn)
= replace_rtx (PATTERN (v->insn), v->dest_reg, v->new_reg);
--- 4612,4618 ----
v->new_reg = gen_reg_rtx (v->mode);
! if (v->derived_from)
{
PATTERN (v->insn)
= replace_rtx (PATTERN (v->insn), v->dest_reg, v->new_reg);
*************** record_giv (v, insn, src_reg, dest_reg,
*** 5264,5270 ****
v->auto_inc_opt = 0;
v->unrolled = 0;
v->shared = 0;
! v->derived = 0;
v->last_use = 0;
/* The v->always_computable field is used in update_giv_derive, to
--- 5263,5269 ----
v->auto_inc_opt = 0;
v->unrolled = 0;
v->shared = 0;
! v->derived_from = 0;
v->last_use = 0;
/* The v->always_computable field is used in update_giv_derive, to
*************** express_from_1 (a, b, mult)
*** 6623,6629 ****
return NULL_RTX;
}
! static rtx
express_from (g1, g2)
struct induction *g1, *g2;
{
--- 6622,6628 ----
return NULL_RTX;
}
! rtx
express_from (g1, g2)
struct induction *g1, *g2;
{
*************** recombine_givs (bl, loop_start, loop_end
*** 7272,7278 ****
rtx sum;
v = giv_array[stats[i].giv_number];
! if (v->giv_type != DEST_REG || v->derived || v->same)
continue;
if (! last_giv)
{
--- 7271,7277 ----
rtx sum;
v = giv_array[stats[i].giv_number];
! if (v->giv_type != DEST_REG || v->derived_from || v->same)
continue;
if (! last_giv)
{
*************** recombine_givs (bl, loop_start, loop_end
*** 7313,7319 ****
gen_rtx_SET (GET_MODE (v->dest_reg),
v->dest_reg, sum), 0))
{
! v->derived = 1;
v->new_reg = v->dest_reg;
life_end = stats[i].end_luid;
}
--- 7312,7318 ----
gen_rtx_SET (GET_MODE (v->dest_reg),
v->dest_reg, sum), 0))
{
! v->derived_from = last_giv;
v->new_reg = v->dest_reg;
life_end = stats[i].end_luid;
}
Index: unroll.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/unroll.c,v
retrieving revision 1.44
diff -p -r1.44 unroll.c
*** unroll.c 1999/01/27 15:45:50 1.44
--- unroll.c 1999/01/29 23:09:41
*************** copy_loop_body (copy_start, copy_end, ma
*** 1801,1806 ****
--- 1801,1810 ----
giv_dest_reg = SET_DEST (set);
if (derived_regs[regno])
{
+ /* ??? This relies on SET_SRC (SET) to be of
+ the form (plus (reg) (const_int)), and thus
+ forces recombine_givs to restrict the kind
+ of giv derivations it does before unrolling. */
giv_src_reg = XEXP (SET_SRC (set), 0);
giv_inc = XEXP (SET_SRC (set), 1);
}
*************** find_splittable_givs (bl, unroll_type, l
*** 2836,2842 ****
}
splittable_regs[REGNO (v->new_reg)] = value;
! derived_regs[REGNO (v->new_reg)] = v->derived;
}
else
{
--- 2840,2846 ----
}
splittable_regs[REGNO (v->new_reg)] = value;
! derived_regs[REGNO (v->new_reg)] = v->derived_from != 0;
}
else
{
*************** find_splittable_givs (bl, unroll_type, l
*** 2892,2899 ****
--- 2896,2914 ----
Emit insn to initialize its value before loop start. */
rtx tem = gen_reg_rtx (v->mode);
+ struct induction *same = v->same;
+ rtx new_reg = v->new_reg;
record_base_value (REGNO (tem), v->add_val, 0);
+ if (same && same->derived_from)
+ {
+ /* Handle V as if the giv from which V->SAME has
+ been derived has been combined with V. */
+
+ same = same->derived_from;
+ new_reg = express_from (same, v);
+ }
+
/* If the address giv has a constant in its new_reg value,
then this constant can be pulled out and put in value,
instead of being part of the initialization code. */
*************** find_splittable_givs (bl, unroll_type, l
*** 2944,2949 ****
--- 2959,2967 ----
INSN_UID (v->insn));
continue;
}
+
+ v->new_reg = new_reg;
+ v->same = same;
/* We set this after the address check, to guarantee that
the register will be initialized. */
*************** find_splittable_givs (bl, unroll_type, l
*** 3020,3026 ****
Make sure that it's giv is marked as splittable here. */
splittable_regs[REGNO (v->new_reg)] = value;
! derived_regs[REGNO (v->new_reg)] = v->derived;
/* Make it appear to depend upon itself, so that the
giv will be properly split in the main loop above. */
--- 3038,3044 ----
Make sure that it's giv is marked as splittable here. */
splittable_regs[REGNO (v->new_reg)] = value;
! derived_regs[REGNO (v->new_reg)] = v->derived_from != 0;
/* Make it appear to depend upon itself, so that the
giv will be properly split in the main loop above. */
*************** find_splittable_givs (bl, unroll_type, l
*** 3061,3067 ****
if (GET_CODE (v->new_reg) == REG)
{
int count = 1;
! if (! v->ignore)
count = reg_biv_class[REGNO (v->src_reg)]->biv_count;
splittable_regs_updates[REGNO (v->new_reg)] = count;
--- 3079,3085 ----
if (GET_CODE (v->new_reg) == REG)
{
int count = 1;
! if (! v->ignore && ! v->derived_from)
count = reg_biv_class[REGNO (v->src_reg)]->biv_count;
splittable_regs_updates[REGNO (v->new_reg)] = count;
More information about the Gcc-patches
mailing list