Fix for PR53397 by making prefecthing less agressive
From-SVN: r192261
This commit is contained in:
parent
eeeef8f4f9
commit
a5497b1238
5 changed files with 149 additions and 18 deletions
|
@ -1,3 +1,21 @@
|
|||
2012-10-09 Venkataramanan Kumar <venkataramanan.kumar@amd.com>
|
||||
|
||||
PR middle-end/53397
|
||||
* tree-ssa-loop-prefetch.c (gather_memory_references_ref):
|
||||
Perform non constant step prefetching in inner loop, only
|
||||
when it is invariant in the entire loop nest.
|
||||
* tree-ssa-loop-prefetch.c (dump_mem_details): New function to dump
|
||||
base, step and delta values of memeory reference analysed for
|
||||
prefetching.
|
||||
* tree-ssa-loop-prefetch.c (dump_mem_ref): Call dump_mem_details
|
||||
to print base, step and delta values of memory reference.
|
||||
* cfgloop.h (loop_outermost): New function that returns outermost
|
||||
loop for a given loop in a loop nest.
|
||||
* testsuite/gcc.dg/pr53397-1.c: New test case
|
||||
Checks we are prefecthing for loop invariant steps
|
||||
* testsuite/gcc.dg/pr53397-2.c: New test case
|
||||
Checks we are not prefecthing for loop variant steps
|
||||
|
||||
2012-10-09 Richard Guenther <rguenther@suse.de>
|
||||
|
||||
PR middle-end/54837
|
||||
|
|
|
@ -712,4 +712,18 @@ extern void move_loop_invariants (void);
|
|||
extern bool finite_loop_p (struct loop *);
|
||||
extern void scale_loop_profile (struct loop *loop, int scale, int iteration_bound);
|
||||
|
||||
/* Returns the outermost loop of the loop nest that contains LOOP.*/
|
||||
static inline struct loop *
|
||||
loop_outermost (struct loop *loop)
|
||||
{
|
||||
|
||||
unsigned n = VEC_length (loop_p, loop->superloops);
|
||||
|
||||
if (n <= 1)
|
||||
return loop;
|
||||
|
||||
return VEC_index (loop_p, loop->superloops, 1);
|
||||
}
|
||||
|
||||
|
||||
#endif /* GCC_CFGLOOP_H */
|
||||
|
|
28
gcc/testsuite/gcc.dg/pr53397-1.c
Normal file
28
gcc/testsuite/gcc.dg/pr53397-1.c
Normal file
|
@ -0,0 +1,28 @@
|
|||
/* Prefetching when the step is loop invariant. */
|
||||
/* { dg-do compile { target { i?86-*-* x86_64-*-* } } } */
|
||||
/* { dg-require-effective-target sse2 } */
|
||||
/* { dg-options "-O3 -fprefetch-loop-arrays -fdump-tree-aprefetch-details --param min-insn-to-prefetch-ratio=3 --param simultaneous-prefetches=10 -fdump-tree-aprefetch-details" } */
|
||||
|
||||
|
||||
double data[16384];
|
||||
void prefetch_when_non_constant_step_is_invariant(int step, int n)
|
||||
{
|
||||
int a;
|
||||
int b;
|
||||
for (a = 1; a < step; a++) {
|
||||
for (b = 0; b < n; b += 2 * step) {
|
||||
|
||||
int i = 2*(b + a);
|
||||
int j = 2*(b + a + step);
|
||||
|
||||
|
||||
data[j] = data[i];
|
||||
data[j+1] = data[i+1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump "Issued prefetch" "aprefetch" } } */
|
||||
/* { dg-final { scan-assembler "prefetcht0" } } */
|
||||
|
||||
/* { dg-final { cleanup-tree-dump "aprefetch" } } */
|
28
gcc/testsuite/gcc.dg/pr53397-2.c
Normal file
28
gcc/testsuite/gcc.dg/pr53397-2.c
Normal file
|
@ -0,0 +1,28 @@
|
|||
/* Not prefetching when the step is loop variant. */
|
||||
/* { dg-do compile { target { i?86-*-* x86_64-*-* } } } */
|
||||
/* { dg-require-effective-target sse2 } */
|
||||
/* { dg-options "-O3 -fprefetch-loop-arrays -fdump-tree-aprefetch-details --param min-insn-to-prefetch-ratio=3 --param simultaneous-prefetches=10 -fdump-tree-aprefetch-details" } */
|
||||
|
||||
double data[16384];
|
||||
void donot_prefetch_when_non_constant_step_is_variant(int step, int n)
|
||||
{
|
||||
int a;
|
||||
int b;
|
||||
for (a = 1; a < step; a++,step*=2) {
|
||||
for (b = 0; b < n; b += 2 * step) {
|
||||
|
||||
int i = 2*(b + a);
|
||||
int j = 2*(b + a + step);
|
||||
|
||||
|
||||
data[j] = data[i];
|
||||
data[j+1] = data[i+1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump "Not prefetching" "aprefetch" } } */
|
||||
/* { dg-final { scan-tree-dump "loop variant step" "aprefetch" } } */
|
||||
|
||||
/* { dg-final { cleanup-tree-dump "aprefetch" } } */
|
||||
|
|
@ -278,6 +278,26 @@ struct mem_ref
|
|||
nontemporal one. */
|
||||
};
|
||||
|
||||
/* Dumps information about memory reference */
|
||||
static void
|
||||
dump_mem_details (FILE *file, tree base, tree step,
|
||||
HOST_WIDE_INT delta, bool write_p)
|
||||
{
|
||||
fprintf (file, "(base ");
|
||||
print_generic_expr (file, base, TDF_SLIM);
|
||||
fprintf (file, ", step ");
|
||||
if (cst_and_fits_in_hwi (step))
|
||||
fprintf (file, HOST_WIDE_INT_PRINT_DEC, int_cst_value (step));
|
||||
else
|
||||
print_generic_expr (file, step, TDF_TREE);
|
||||
fprintf (file, ")\n");
|
||||
fprintf (file, " delta ");
|
||||
fprintf (file, HOST_WIDE_INT_PRINT_DEC, delta);
|
||||
fprintf (file, "\n");
|
||||
fprintf (file, " %s\n", write_p ? "write" : "read");
|
||||
fprintf (file, "\n");
|
||||
}
|
||||
|
||||
/* Dumps information about reference REF to FILE. */
|
||||
|
||||
static void
|
||||
|
@ -285,22 +305,10 @@ dump_mem_ref (FILE *file, struct mem_ref *ref)
|
|||
{
|
||||
fprintf (file, "Reference %p:\n", (void *) ref);
|
||||
|
||||
fprintf (file, " group %p (base ", (void *) ref->group);
|
||||
print_generic_expr (file, ref->group->base, TDF_SLIM);
|
||||
fprintf (file, ", step ");
|
||||
if (cst_and_fits_in_hwi (ref->group->step))
|
||||
fprintf (file, HOST_WIDE_INT_PRINT_DEC, int_cst_value (ref->group->step));
|
||||
else
|
||||
print_generic_expr (file, ref->group->step, TDF_TREE);
|
||||
fprintf (file, ")\n");
|
||||
fprintf (file, " group %p ", (void *) ref->group);
|
||||
|
||||
fprintf (file, " delta ");
|
||||
fprintf (file, HOST_WIDE_INT_PRINT_DEC, ref->delta);
|
||||
fprintf (file, "\n");
|
||||
|
||||
fprintf (file, " %s\n", ref->write_p ? "write" : "read");
|
||||
|
||||
fprintf (file, "\n");
|
||||
dump_mem_details (file, ref->group->base, ref->group->step, ref->delta,
|
||||
ref->write_p);
|
||||
}
|
||||
|
||||
/* Finds a group with BASE and STEP in GROUPS, or creates one if it does not
|
||||
|
@ -537,9 +545,44 @@ gather_memory_references_ref (struct loop *loop, struct mem_ref_group **refs,
|
|||
if (may_be_nonaddressable_p (base))
|
||||
return false;
|
||||
|
||||
/* Limit non-constant step prefetching only to the innermost loops. */
|
||||
if (!cst_and_fits_in_hwi (step) && loop->inner != NULL)
|
||||
return false;
|
||||
/* Limit non-constant step prefetching only to the innermost loops and
|
||||
only when the step is loop invariant in the entire loop nest. */
|
||||
if (!cst_and_fits_in_hwi (step))
|
||||
{
|
||||
if (loop->inner != NULL)
|
||||
{
|
||||
if (dump_file && (dump_flags & TDF_DETAILS))
|
||||
{
|
||||
fprintf (dump_file, "Memory expression %p\n",(void *) ref );
|
||||
print_generic_expr (dump_file, ref, TDF_TREE);
|
||||
fprintf (dump_file,":");
|
||||
dump_mem_details( dump_file, base, step, delta, write_p);
|
||||
fprintf (dump_file,
|
||||
"Ignoring %p, non-constant step prefetching is "
|
||||
"limited to inner most loops \n",
|
||||
(void *) ref);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!expr_invariant_in_loop_p (loop_outermost (loop), step))
|
||||
{
|
||||
if (dump_file && (dump_flags & TDF_DETAILS))
|
||||
{
|
||||
fprintf (dump_file, "Memory expression %p\n",(void *) ref );
|
||||
print_generic_expr (dump_file, ref, TDF_TREE);
|
||||
fprintf (dump_file,":");
|
||||
dump_mem_details(dump_file, base, step, delta, write_p);
|
||||
fprintf (dump_file,
|
||||
"Not prefetching, ignoring %p due to "
|
||||
"loop variant step\n",
|
||||
(void *) ref);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Now we know that REF = &BASE + STEP * iter + DELTA, where DELTA and STEP
|
||||
are integer constants. */
|
||||
|
|
Loading…
Add table
Reference in a new issue