fix PR68693: Check for loop structure when extending the SCoP

The check for dominance while extending the scop assumed that
multiple successors meant a loop which is not true in case of
conditionals around the loop.

Improved pretty printers for better debugging.

	PR tree-optimization/68693
        * graphite-scop-detection.c (dot_all_sese): New
        (dot_all_scops_1): Renamed to dot_all_sese.
        (dot_all_scops): Removed.
        (dot_sese): New.
        (dot_cfg): New.
        (scop_detection::get_nearest_dom_with_single_entry): Check that preds are from different loop levels.
        (scop_detection::get_nearest_pdom_with_single_exit): Check that succs are from different loop levels.
        (scop_detection::print_sese): Inlined.
        (scop_detection::print_edge): New.
        (scop_detection::merge_sese): Added dumps.
        * graphite.h: Add declarations.

gcc/testsuite/ChangeLog:

        * gfortran.dg/graphite/pr68693.f90: New test.

Co-Authored-By: Sebastian Pop <s.pop@samsung.com>

From-SVN: r231309
This commit is contained in:
Aditya Kumar 2015-12-04 21:36:55 +00:00 committed by Sebastian Pop
parent bdf5848047
commit 15256e28a5
5 changed files with 134 additions and 84 deletions

View File

@ -1,3 +1,21 @@
2015-12-04 Aditya Kumar <aditya.k7@samsung.com>
Sebastian Pop <s.pop@samsung.com>
PR tree-optimization/68693
* graphite-scop-detection.c (dot_all_sese): New
(dot_all_scops_1): Renamed to dot_all_sese.
(dot_all_scops): Removed.
(dot_sese): New.
(dot_cfg): New.
(scop_detection::get_nearest_dom_with_single_entry): Check that
preds are from different loop levels.
(scop_detection::get_nearest_pdom_with_single_exit): Check that
succs are from different loop levels.
(scop_detection::print_sese): Inlined.
(scop_detection::print_edge): New.
(scop_detection::merge_sese): Added dumps.
* graphite.h: Add declarations.
2015-12-04 James Greenhalgh <james.greenhalgh@arm.com>
* config/aarch64/aarch64.md (add<mode>3_pluslong): Add register

View File

@ -98,22 +98,16 @@ public:
- "()" around the node number denotes the entry or the
exit nodes of the SCOP. These are not part of SCoP. */
static void
dot_all_scops_1 (FILE *file, vec<scop_p> scops)
DEBUG_FUNCTION void
dot_all_sese (FILE *file, vec<sese_l>& scops)
{
basic_block bb;
edge e;
edge_iterator ei;
scop_p scop;
const char *color;
int i;
/* Disable debugging while printing graph. */
int tmp_dump_flags = dump_flags;
dump_flags = 0;
fprintf (file, "digraph all {\n");
basic_block bb;
FOR_ALL_BB_FN (bb, cfun)
{
int part_of_scop = false;
@ -126,12 +120,15 @@ dot_all_scops_1 (FILE *file, vec<scop_p> scops)
fprintf (file, "CELLSPACING=\"0\">\n");
/* Select color for SCoP. */
FOR_EACH_VEC_ELT (scops, i, scop)
sese_l *region;
int i;
FOR_EACH_VEC_ELT (scops, i, region)
{
sese_l region = scop->scop_info->region;
if (bb_in_sese_p (bb, region) || (region.exit->dest == bb)
|| (region.entry->dest == bb))
bool sese_in_region = bb_in_sese_p (bb, *region);
if (sese_in_region || (region->exit->dest == bb)
|| (region->entry->dest == bb))
{
const char *color;
switch (i % 17)
{
case 0: /* red */
@ -192,21 +189,21 @@ dot_all_scops_1 (FILE *file, vec<scop_p> scops)
fprintf (file, " <TR><TD WIDTH=\"50\" BGCOLOR=\"%s\">",
color);
if (!bb_in_sese_p (bb, region))
if (!sese_in_region)
fprintf (file, " (");
if (bb == region.entry->dest && bb == region.exit->dest)
if (bb == region->entry->dest && bb == region->exit->dest)
fprintf (file, " %d*# ", bb->index);
else if (bb == region.entry->dest)
else if (bb == region->entry->dest)
fprintf (file, " %d* ", bb->index);
else if (bb == region.exit->dest)
else if (bb == region->exit->dest)
fprintf (file, " %d# ", bb->index);
else
fprintf (file, " %d ", bb->index);
fprintf (file, "{lp_%d}", bb->loop_father->num);
if (!bb_in_sese_p (bb, region))
if (!sese_in_region)
fprintf (file, ")");
fprintf (file, "</TD></TR>\n");
@ -225,6 +222,8 @@ dot_all_scops_1 (FILE *file, vec<scop_p> scops)
FOR_ALL_BB_FN (bb, cfun)
{
edge e;
edge_iterator ei;
FOR_EACH_EDGE (e, ei, bb->succs)
fprintf (file, "%d -> %d;\n", bb->index, e->dest->index);
}
@ -235,52 +234,29 @@ dot_all_scops_1 (FILE *file, vec<scop_p> scops)
dump_flags = tmp_dump_flags;
}
/* Display all SCoPs using dotty. */
/* Display SCoP on stderr. */
DEBUG_FUNCTION void
dot_all_scops (vec<scop_p> scops)
dot_sese (sese_l& scop)
{
/* When debugging, enable the following code. This cannot be used
in production compilers because it calls "system". */
#if 0
int x;
FILE *stream = fopen ("/tmp/allscops.dot", "w");
gcc_assert (stream);
dot_all_scops_1 (stream, scops);
fclose (stream);
x = system ("dotty /tmp/allscops.dot &");
#else
dot_all_scops_1 (stderr, scops);
#endif
}
/* Display all SCoPs using dotty. */
DEBUG_FUNCTION void
dot_scop (scop_p scop)
{
auto_vec<scop_p, 1> scops;
vec<sese_l> scops;
scops.create (1);
if (scop)
scops.safe_push (scop);
/* When debugging, enable the following code. This cannot be used
in production compilers because it calls "system". */
#if 0
{
int x;
FILE *stream = fopen ("/tmp/allscops.dot", "w");
gcc_assert (stream);
dot_all_sese (stderr, scops);
dot_all_scops_1 (stream, scops);
fclose (stream);
x = system ("dotty /tmp/allscops.dot &");
}
#else
dot_all_scops_1 (stderr, scops);
#endif
scops.release ();
}
DEBUG_FUNCTION void
dot_cfg ()
{
vec<sese_l> scops;
scops.create (1);
dot_all_sese (stderr, scops);
scops.release ();
}
/* Return true if BB is empty, contains only DEBUG_INSNs. */
@ -552,9 +528,20 @@ public:
static edge get_nearest_pdom_with_single_exit (basic_block dom);
/* Print S to FILE. */
static void print_sese (FILE *file, sese_l s);
/* Pretty printers. */
static void print_edge (FILE *file, const_edge e)
{
fprintf (file, "edge (bb_%d, bb_%d)", e->src->index, e->dest->index);
}
static void print_sese (FILE *file, sese_l s)
{
fprintf (file, "(entry_"); print_edge (file, s.entry);
fprintf (file, ", exit_"); print_edge (file, s.exit);
fprintf (file, ")\n");
}
/* Merge scops at same loop depth and returns the new sese.
Returns a new SESE when merge was successful, INVALID_SESE otherwise. */
@ -717,9 +704,14 @@ scop_detection::get_nearest_dom_with_single_entry (basic_block dom)
{
edge e1 = (*dom->preds)[0];
edge e2 = (*dom->preds)[1];
if (dominated_by_p (CDI_DOMINATORS, e2->src, e1->src))
loop_p l = dom->loop_father;
loop_p l1 = e1->src->loop_father;
loop_p l2 = e2->src->loop_father;
if (l != l1
&& dominated_by_p (CDI_DOMINATORS, e2->src, e1->src))
return e1;
if (dominated_by_p (CDI_DOMINATORS, e1->src, e2->src))
if (l != l2
&& dominated_by_p (CDI_DOMINATORS, e1->src, e2->src))
return e2;
}
@ -738,39 +730,35 @@ scop_detection::get_nearest_dom_with_single_entry (basic_block dom)
back-loop the back-edge is not counted. */
edge
scop_detection::get_nearest_pdom_with_single_exit (basic_block dom)
scop_detection::get_nearest_pdom_with_single_exit (basic_block pdom)
{
if (!dom->succs)
if (!pdom->succs)
return NULL;
if (dom->succs->length () == 2)
if (pdom->succs->length () == 2)
{
edge e1 = (*dom->succs)[0];
edge e2 = (*dom->succs)[1];
if (dominated_by_p (CDI_POST_DOMINATORS, e2->dest, e1->dest))
edge e1 = (*pdom->succs)[0];
edge e2 = (*pdom->succs)[1];
loop_p l = pdom->loop_father;
loop_p l1 = e1->dest->loop_father;
loop_p l2 = e2->dest->loop_father;
if (l != l1
&& dominated_by_p (CDI_POST_DOMINATORS, e2->dest, e1->dest))
return e1;
if (dominated_by_p (CDI_POST_DOMINATORS, e1->dest, e2->dest))
if (l != l2
&& dominated_by_p (CDI_POST_DOMINATORS, e1->dest, e2->dest))
return e2;
}
while (dom->succs->length () != 1)
while (pdom->succs->length () != 1)
{
if (dom->succs->length () < 1)
if (pdom->succs->length () < 1)
return NULL;
dom = get_immediate_dominator (CDI_POST_DOMINATORS, dom);
if (!dom->succs)
pdom = get_immediate_dominator (CDI_POST_DOMINATORS, pdom);
if (!pdom->succs)
return NULL;
}
return (*dom->succs)[0];
}
/* Print S to FILE. */
void
scop_detection::print_sese (FILE *file, sese_l s)
{
fprintf (file, "(entry_edge (bb_%d, bb_%d), exit_edge (bb_%d, bb_%d))\n",
s.entry->src->index, s.entry->dest->index,
s.exit->src->index, s.exit->dest->index);
return (*pdom->succs)[0];
}
/* Merge scops at same loop depth and returns the new sese.
@ -815,6 +803,9 @@ scop_detection::merge_sese (sese_l first, sese_l second) const
sese_l combined (entry, exit);
DEBUG_PRINT (dp << "checking combined sese: ";
print_sese (dump_file, combined));
/* FIXME: We could iterate to find the dom which dominates pdom, and pdom
which post-dominates dom, until it stabilizes. Also, ENTRY->SRC and
EXIT->DEST should be in the same loop nest. */

View File

@ -465,7 +465,7 @@ extern bool build_poly_scop (scop_p);
extern bool graphite_regenerate_ast_isl (scop_p);
extern void build_scops (vec<scop_p> *);
extern void dot_all_scops (vec<scop_p>);
extern void dot_scop (scop_p);
extern void dot_all_sese (FILE *, vec<sese_l> &);
extern void dot_sese (sese_l &);
extern void dot_cfg ();
#endif

View File

@ -1,3 +1,9 @@
2015-12-04 Aditya Kumar <aditya.k7@samsung.com>
Sebastian Pop <s.pop@samsung.com>
PR tree-optimization/68693
* gfortran.dg/graphite/pr68693.f90: New test.
2015-12-04 James Greenhalgh <james.greenhalgh@arm.com>
* gcc.c-torture/compile/20151204.c: New.

View File

@ -0,0 +1,35 @@
! { dg-options "-floop-nest-optimize -O2" }
MODULE dbcsr_index_operations
INTERFACE dbcsr_build_row_index
END INTERFACE
CONTAINS
SUBROUTINE merge_index_arrays (new_row_i, new_col_i, new_blk_p, new_size,&
old_row_i, old_col_i, old_blk_p, old_size,&
add_ip, add_size, new_blk_d, old_blk_d,&
added_size_offset, added_sizes, added_size, added_nblks, error)
INTEGER, DIMENSION(new_size), &
INTENT(OUT) :: new_blk_p, new_col_i, &
new_row_i
INTEGER, INTENT(IN) :: old_size
INTEGER, DIMENSION(old_size), INTENT(IN) :: old_blk_p, old_col_i, &
old_row_i
INTEGER, DIMENSION(new_size), &
INTENT(OUT), OPTIONAL :: new_blk_d
INTEGER, DIMENSION(old_size), &
INTENT(IN), OPTIONAL :: old_blk_d
INTEGER, DIMENSION(:), INTENT(IN), &
OPTIONAL :: added_sizes
INTEGER, INTENT(OUT), OPTIONAL :: added_size, added_nblks
LOGICAL :: multidata
IF (add_size .GT. 0) THEN
IF (old_size .EQ. 0) THEN
IF (PRESENT (added_size)) added_size = SUM (added_sizes)
ENDIF
ELSE
new_row_i(1:old_size) = old_row_i(1:old_size)
new_col_i(1:old_size) = old_col_i(1:old_size)
new_blk_p(1:old_size) = old_blk_p(1:old_size)
IF (multidata) new_blk_d(1:old_size) = old_blk_d(1:old_size)
ENDIF
END SUBROUTINE merge_index_arrays
END MODULE dbcsr_index_operations