This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Fixes to latest loop.c changes for prefetching
- From: kenner at vlsi1 dot ultra dot nyu dot edu (Richard Kenner)
- To: gcc-patches at gcc dot gnu dot org
- Date: Thu, 13 Dec 01 09:18:10 EST
- Subject: Fixes to latest loop.c changes for prefetching
There is a prototype conflict on Alpha and some warnings, which I fixed,
but I also made a pass at cleaning up whitespace in some of the new
code.
Thu Dec 13 07:47:24 2001 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
* loop.c (remove_constant_addition): Fix prototype and whitespace.
(emit_prefetch_instructions): Remove warnings and whitespace
changes.
*** loop.c 2001/12/13 11:34:05 1.370
--- loop.c 2001/12/13 12:40:58
*************** static rtx loop_insn_sink_or_swim PARAMS
*** 347,351 ****
static void loop_dump_aux PARAMS ((const struct loop *, FILE *, int));
static void loop_delete_insns PARAMS ((rtx, rtx));
! static int remove_constant_addition PARAMS ((rtx *));
void debug_ivs PARAMS ((const struct loop *));
void debug_iv_class PARAMS ((const struct iv_class *));
--- 347,351 ----
static void loop_dump_aux PARAMS ((const struct loop *, FILE *, int));
static void loop_delete_insns PARAMS ((rtx, rtx));
! static HOST_WIDE_INT remove_constant_addition PARAMS ((rtx *));
void debug_ivs PARAMS ((const struct loop *));
void debug_iv_class PARAMS ((const struct iv_class *));
*************** rtx_equal_for_prefetch_p (x, y)
*** 3635,3638 ****
--- 3635,3639 ----
/* Remove constant addition value from the expression X (when present)
and return it. */
+
static HOST_WIDE_INT
remove_constant_addition (x)
*************** remove_constant_addition (x)
*** 3640,3644 ****
{
HOST_WIDE_INT addval = 0;
! rtx exp=*x;
if (GET_CODE (exp) == CONST)
--- 3641,3645 ----
{
HOST_WIDE_INT addval = 0;
! rtx exp = *x;
if (GET_CODE (exp) == CONST)
*************** remove_constant_addition (x)
*** 3649,3652 ****
--- 3650,3654 ----
*x = const0_rtx;
}
+
/* For plus expression recurse on ourself. */
else if (GET_CODE (exp) == PLUS)
*************** remove_constant_addition (x)
*** 3654,3659 ****
addval += remove_constant_addition (&XEXP (exp, 0));
addval += remove_constant_addition (&XEXP (exp, 1));
! /* In case our parameter was constant, remove extra zero
! from the expression. */
if (XEXP (exp, 0) == const0_rtx)
*x = XEXP (exp, 1);
--- 3656,3662 ----
addval += remove_constant_addition (&XEXP (exp, 0));
addval += remove_constant_addition (&XEXP (exp, 1));
!
! /* In case our parameter was constant, remove extra zero from the
! expression. */
if (XEXP (exp, 0) == const0_rtx)
*x = XEXP (exp, 1);
*************** remove_constant_addition (x)
*** 3661,3664 ****
--- 3664,3668 ----
*x = XEXP (exp, 0);
}
+
return addval;
}
*************** remove_constant_addition (x)
*** 3682,3689 ****
Several heuristics are used to determine when to prefetch. They are
! controlled by defined symbols that can be overridden for each target.
! */
static void
! emit_prefetch_instructions (struct loop *loop)
{
int num_prefetches = 0;
--- 3686,3694 ----
Several heuristics are used to determine when to prefetch. They are
! controlled by defined symbols that can be overridden for each target. */
!
static void
! emit_prefetch_instructions (loop)
! struct loop *loop;
{
int num_prefetches = 0;
*************** emit_prefetch_instructions (struct loop
*** 3706,3709 ****
--- 3711,3715 ----
if (loop_dump_stream)
fprintf (loop_dump_stream, "Prefetch: ignoring loop - has call.\n");
+
return;
}
*************** emit_prefetch_instructions (struct loop
*** 3727,3730 ****
--- 3733,3737 ----
biv1 = biv;
+
/* Expect all BIVs to be executed in each iteration. This makes our
analysis more conservative. */
*************** emit_prefetch_instructions (struct loop
*** 3737,3746 ****
heuristics more conservative.
??? What does the last sentence mean? */
-
if (GET_CODE (biv->add_val) != CONST_INT)
{
if (loop_dump_stream)
{
! fprintf (loop_dump_stream, "Prefetch: biv %i ignored: non-constant addition at insn %i:",
REGNO (biv->src_reg), INSN_UID (biv->insn));
print_rtl (loop_dump_stream, biv->add_val);
--- 3744,3753 ----
heuristics more conservative.
??? What does the last sentence mean? */
if (GET_CODE (biv->add_val) != CONST_INT)
{
if (loop_dump_stream)
{
! fprintf (loop_dump_stream,
! "Prefetch: biv %i ignored: non-constant addition at insn %i:",
REGNO (biv->src_reg), INSN_UID (biv->insn));
print_rtl (loop_dump_stream, biv->add_val);
*************** emit_prefetch_instructions (struct loop
*** 3749,3757 ****
break;
}
if (biv->maybe_multiple)
{
if (loop_dump_stream)
{
! fprintf (loop_dump_stream, "Prefetch: biv %i ignored: maybe_multiple at insn %i:",
REGNO (biv->src_reg), INSN_UID (biv->insn));
print_rtl (loop_dump_stream, biv->add_val);
--- 3756,3766 ----
break;
}
+
if (biv->maybe_multiple)
{
if (loop_dump_stream)
{
! fprintf (loop_dump_stream,
! "Prefetch: biv %i ignored: maybe_multiple at insn %i:",
REGNO (biv->src_reg), INSN_UID (biv->insn));
print_rtl (loop_dump_stream, biv->add_val);
*************** emit_prefetch_instructions (struct loop
*** 3760,3768 ****
--- 3769,3780 ----
break;
}
+
basestride += INTVAL (biv1->add_val);
biv1 = biv1->next_iv;
}
+
if (biv1 || !basestride)
continue;
+
for (iv = bl->giv; iv; iv = iv->next_iv)
{
*************** emit_prefetch_instructions (struct loop
*** 3778,3804 ****
interesting to us. */
if (iv->giv_type != DEST_ADDR
! /* We are interested only in constant stride memory references
! in order to be able to compute density easily. */
|| GET_CODE (iv->mult_val) != CONST_INT
! /* Don't handle reversed order prefetches, since they are usually
! ineffective. Later we may be able to reverse such BIVs. */
|| (PREFETCH_NO_REVERSE_ORDER
&& (stride = INTVAL (iv->mult_val) * basestride) < 0)
! /* Prefetching of accesses with such a extreme stride is probably
! not worthwhile, either. */
|| (PREFETCH_NO_EXTREME_STRIDE
&& stride > PREFETCH_EXTREME_STRIDE)
! /* Ignore GIVs with varying add values; we can't predict the value
! for the next iteration. */
|| !loop_invariant_p (loop, iv->add_val)
! /* Ignore GIVs in the nested loops; they ought to have been handled
! already. */
|| iv->maybe_multiple)
{
if (loop_dump_stream)
! {
! fprintf (loop_dump_stream, "Prefetch: Ignoring giv at %i\n",
! INSN_UID (iv->insn));
! }
continue;
}
--- 3790,3814 ----
interesting to us. */
if (iv->giv_type != DEST_ADDR
! /* We are interested only in constant stride memory references
! in order to be able to compute density easily. */
|| GET_CODE (iv->mult_val) != CONST_INT
! /* Don't handle reversed order prefetches, since they are usually
! ineffective. Later we may be able to reverse such BIVs. */
|| (PREFETCH_NO_REVERSE_ORDER
&& (stride = INTVAL (iv->mult_val) * basestride) < 0)
! /* Prefetching of accesses with such a extreme stride is probably
! not worthwhile, either. */
|| (PREFETCH_NO_EXTREME_STRIDE
&& stride > PREFETCH_EXTREME_STRIDE)
! /* Ignore GIVs with varying add values; we can't predict the
! value for the next iteration. */
|| !loop_invariant_p (loop, iv->add_val)
! /* Ignore GIVs in the nested loops; they ought to have been
! handled already. */
|| iv->maybe_multiple)
{
if (loop_dump_stream)
! fprintf (loop_dump_stream, "Prefetch: Ignoring giv at %i\n",
! INSN_UID (iv->insn));
continue;
}
*************** emit_prefetch_instructions (struct loop
*** 3817,3820 ****
--- 3827,3831 ----
d.mem_write = 0;
d.mem_address = *iv->location;
+
/* When the GIV is not always executed, we might be better off by
not dirtying the cache pages. */
*************** emit_prefetch_instructions (struct loop
*** 3835,3839 ****
but also not bigger than small portion of memory usually
traversed by single loop. */
-
if (index >= info[i].index && index - info[i].index < 4096)
{
--- 3846,3849 ----
*************** emit_prefetch_instructions (struct loop
*** 3847,3850 ****
--- 3857,3861 ----
break;
}
+
if (index < info[i].index && info[i].index - index < 4096)
{
*************** emit_prefetch_instructions (struct loop
*** 3855,3858 ****
--- 3866,3870 ----
}
}
+
/* Merging failed. */
if (add)
*************** emit_prefetch_instructions (struct loop
*** 3869,3873 ****
{
if (loop_dump_stream)
! fprintf(loop_dump_stream,"Maximal number of prefetches exceeded.\n");
return;
}
--- 3881,3886 ----
{
if (loop_dump_stream)
! fprintf (loop_dump_stream,
! "Maximal number of prefetches exceeded.\n");
return;
}
*************** emit_prefetch_instructions (struct loop
*** 3875,3878 ****
--- 3888,3892 ----
}
}
+
for (i = 0; i < num_prefetches; i++)
{
*************** emit_prefetch_instructions (struct loop
*** 3880,3901 ****
Avoid overflow. */
if (LOOP_INFO (loop)->n_iterations
! && (0xffffffff / info[i].stride) >= LOOP_INFO (loop)->n_iterations)
info[i].total_bytes = info[i].stride * LOOP_INFO (loop)->n_iterations;
else
info[i].total_bytes = 0xffffffff;
-
/* Prefetch is worthwhile only when the loads/stores are dense. */
if (PREFETCH_ONLY_DENSE_MEM
! && (info[i].bytes_accesed * 256 / info[i].stride > PREFETCH_DENSE_MEM)
! && (info[i].total_bytes / PREFETCH_BLOCK >=
! PREFETCH_BLOCKS_BEFORE_LOOP_MIN))
{
info[i].prefetch_before_loop = 1;
! if (info[i].total_bytes / PREFETCH_BLOCK <=
! PREFETCH_BLOCKS_BEFORE_LOOP_MAX)
! info[i].prefetch_in_loop = 0;
! else
! info[i].prefetch_in_loop = 1;
}
else
--- 3894,3913 ----
Avoid overflow. */
if (LOOP_INFO (loop)->n_iterations
! && ((unsigned HOST_WIDE_INT) (0xffffffff / info[i].stride)
! >= LOOP_INFO (loop)->n_iterations))
info[i].total_bytes = info[i].stride * LOOP_INFO (loop)->n_iterations;
else
info[i].total_bytes = 0xffffffff;
/* Prefetch is worthwhile only when the loads/stores are dense. */
if (PREFETCH_ONLY_DENSE_MEM
! && info[i].bytes_accesed * 256 / info[i].stride > PREFETCH_DENSE_MEM
! && (info[i].total_bytes / PREFETCH_BLOCK
! >= PREFETCH_BLOCKS_BEFORE_LOOP_MIN))
{
info[i].prefetch_before_loop = 1;
! info[i].prefetch_in_loop
! = (info[i].total_bytes / PREFETCH_BLOCK
! > PREFETCH_BLOCKS_BEFORE_LOOP_MAX);
}
else
*************** emit_prefetch_instructions (struct loop
*** 3907,3914 ****
/ PREFETCH_BLOCK);
if (info[i].write)
! num_real_write_prefetches +=
! ((info[i].stride + PREFETCH_BLOCK - 1) / PREFETCH_BLOCK);
}
}
if (loop_dump_stream)
{
--- 3919,3927 ----
/ PREFETCH_BLOCK);
if (info[i].write)
! num_real_write_prefetches
! += (info[i].stride + PREFETCH_BLOCK - 1) / PREFETCH_BLOCK;
}
}
+
if (loop_dump_stream)
{
*************** emit_prefetch_instructions (struct loop
*** 3918,3930 ****
INSN_UID (info[i].giv->insn));
print_rtl (loop_dump_stream, info[i].base_address);
! fprintf (loop_dump_stream, " Index:%i stride:%i density:%i%% total_bytes: %u %s in loop:%s before:%s\n",
! info[i].index, info[i].stride,
! info[i].bytes_accesed * 100 / info[i].stride,
info[i].total_bytes,
! info[i].write ? "read/write" : "read only",
info[i].prefetch_in_loop ? "yes" : "no",
info[i].prefetch_before_loop ? "yes" : "no");
}
! fprintf (loop_dump_stream, "Real prefetches needed:%i (write:%i)\n",
num_real_prefetches, num_real_write_prefetches);
}
--- 3931,3948 ----
INSN_UID (info[i].giv->insn));
print_rtl (loop_dump_stream, info[i].base_address);
! fprintf (loop_dump_stream, " Index: ");
! fprintf (loop_dump_stream, HOST_WIDE_INT_PRINT_DEC, info[i].index);
! fprintf (loop_dump_stream, " stride: ");
! fprintf (loop_dump_stream, HOST_WIDE_INT_PRINT_DEC, info[i].stride);
! fprintf (loop_dump_stream,
! " density: %i%% total_bytes: %u%sin loop: %s before: %s\n",
! (int) (info[i].bytes_accesed * 100 / info[i].stride),
info[i].total_bytes,
! info[i].write ? " read/write " : " read only ",
info[i].prefetch_in_loop ? "yes" : "no",
info[i].prefetch_before_loop ? "yes" : "no");
}
!
! fprintf (loop_dump_stream, "Real prefetches needed: %i (write: %i)\n",
num_real_prefetches, num_real_write_prefetches);
}
*************** emit_prefetch_instructions (struct loop
*** 3933,3940 ****
return;
! ahead = (SIMULTANEOUS_PREFETCHES / (num_real_prefetches));
if (!ahead)
return;
for (i = 0; i < num_prefetches; i++)
{
--- 3951,3959 ----
return;
! ahead = SIMULTANEOUS_PREFETCHES / num_real_prefetches;
if (!ahead)
return;
+
for (i = 0; i < num_prefetches; i++)
{
*************** emit_prefetch_instructions (struct loop
*** 3942,3945 ****
--- 3961,3965 ----
{
int y;
+
for (y = 0; y < ((info[i].stride + PREFETCH_BLOCK - 1)
/ PREFETCH_BLOCK); y++)
*************** emit_prefetch_instructions (struct loop
*** 3965,3971 ****
emit_insn_before (gen_prefetch (loc, GEN_INT (info[i].write),
! GEN_INT (3)), before_insn);
! /* Check all insns emitted and record the new GIV information. */
insn = NEXT_INSN (prev_insn);
while (insn != before_insn)
--- 3985,3993 ----
emit_insn_before (gen_prefetch (loc, GEN_INT (info[i].write),
! GEN_INT (3)),
! before_insn);
! /* Check all insns emitted and record the new GIV
! information. */
insn = NEXT_INSN (prev_insn);
while (insn != before_insn)
*************** emit_prefetch_instructions (struct loop
*** 3978,3987 ****
}
}
if (info[i].prefetch_before_loop)
{
int y;
/* Emit INSNs before the loop to fetch the first cache lines. */
! for (y = 0; ((!info[i].prefetch_in_loop || y < ahead)
! && y * PREFETCH_BLOCK < (int)info[i].total_bytes); y ++)
{
rtx reg = gen_reg_rtx (Pmode);
--- 4000,4012 ----
}
}
+
if (info[i].prefetch_before_loop)
{
int y;
+
/* Emit INSNs before the loop to fetch the first cache lines. */
! for (y = 0;
! (!info[i].prefetch_in_loop || y < ahead)
! && y * PREFETCH_BLOCK < (int) info[i].total_bytes; y ++)
{
rtx reg = gen_reg_rtx (Pmode);
*************** emit_prefetch_instructions (struct loop
*** 3990,4001 ****
info[i].giv->add_val,
GEN_INT (y * PREFETCH_BLOCK));
loop_iv_add_mult_emit_before (loop, info[i].class->initial_value,
info[i].giv->mult_val,
add_val, reg, 0, loop_start);
emit_insn_before (gen_prefetch (reg, GEN_INT (info[i].write),
! GEN_INT (3)), loop_start);
}
}
}
return;
}
--- 4015,4029 ----
info[i].giv->add_val,
GEN_INT (y * PREFETCH_BLOCK));
+
loop_iv_add_mult_emit_before (loop, info[i].class->initial_value,
info[i].giv->mult_val,
add_val, reg, 0, loop_start);
emit_insn_before (gen_prefetch (reg, GEN_INT (info[i].write),
! GEN_INT (3)),
! loop_start);
}
}
}
+
return;
}