Commit 15256e28 by Aditya Kumar Committed by Sebastian Pop

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
parent bdf58480
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> 2015-12-04 James Greenhalgh <james.greenhalgh@arm.com>
* config/aarch64/aarch64.md (add<mode>3_pluslong): Add register * config/aarch64/aarch64.md (add<mode>3_pluslong): Add register
...@@ -98,22 +98,16 @@ public: ...@@ -98,22 +98,16 @@ public:
- "()" around the node number denotes the entry or the - "()" around the node number denotes the entry or the
exit nodes of the SCOP. These are not part of SCoP. */ exit nodes of the SCOP. These are not part of SCoP. */
static void DEBUG_FUNCTION void
dot_all_scops_1 (FILE *file, vec<scop_p> scops) 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. */ /* Disable debugging while printing graph. */
int tmp_dump_flags = dump_flags; int tmp_dump_flags = dump_flags;
dump_flags = 0; dump_flags = 0;
fprintf (file, "digraph all {\n"); fprintf (file, "digraph all {\n");
basic_block bb;
FOR_ALL_BB_FN (bb, cfun) FOR_ALL_BB_FN (bb, cfun)
{ {
int part_of_scop = false; int part_of_scop = false;
...@@ -126,12 +120,15 @@ dot_all_scops_1 (FILE *file, vec<scop_p> scops) ...@@ -126,12 +120,15 @@ dot_all_scops_1 (FILE *file, vec<scop_p> scops)
fprintf (file, "CELLSPACING=\"0\">\n"); fprintf (file, "CELLSPACING=\"0\">\n");
/* Select color for SCoP. */ /* 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; bool sese_in_region = bb_in_sese_p (bb, *region);
if (bb_in_sese_p (bb, region) || (region.exit->dest == bb) if (sese_in_region || (region->exit->dest == bb)
|| (region.entry->dest == bb)) || (region->entry->dest == bb))
{ {
const char *color;
switch (i % 17) switch (i % 17)
{ {
case 0: /* red */ case 0: /* red */
...@@ -192,21 +189,21 @@ dot_all_scops_1 (FILE *file, vec<scop_p> scops) ...@@ -192,21 +189,21 @@ dot_all_scops_1 (FILE *file, vec<scop_p> scops)
fprintf (file, " <TR><TD WIDTH=\"50\" BGCOLOR=\"%s\">", fprintf (file, " <TR><TD WIDTH=\"50\" BGCOLOR=\"%s\">",
color); color);
if (!bb_in_sese_p (bb, region)) if (!sese_in_region)
fprintf (file, " ("); 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); fprintf (file, " %d*# ", bb->index);
else if (bb == region.entry->dest) else if (bb == region->entry->dest)
fprintf (file, " %d* ", bb->index); fprintf (file, " %d* ", bb->index);
else if (bb == region.exit->dest) else if (bb == region->exit->dest)
fprintf (file, " %d# ", bb->index); fprintf (file, " %d# ", bb->index);
else else
fprintf (file, " %d ", bb->index); fprintf (file, " %d ", bb->index);
fprintf (file, "{lp_%d}", bb->loop_father->num); fprintf (file, "{lp_%d}", bb->loop_father->num);
if (!bb_in_sese_p (bb, region)) if (!sese_in_region)
fprintf (file, ")"); fprintf (file, ")");
fprintf (file, "</TD></TR>\n"); fprintf (file, "</TD></TR>\n");
...@@ -225,6 +222,8 @@ dot_all_scops_1 (FILE *file, vec<scop_p> scops) ...@@ -225,6 +222,8 @@ dot_all_scops_1 (FILE *file, vec<scop_p> scops)
FOR_ALL_BB_FN (bb, cfun) FOR_ALL_BB_FN (bb, cfun)
{ {
edge e;
edge_iterator ei;
FOR_EACH_EDGE (e, ei, bb->succs) FOR_EACH_EDGE (e, ei, bb->succs)
fprintf (file, "%d -> %d;\n", bb->index, e->dest->index); fprintf (file, "%d -> %d;\n", bb->index, e->dest->index);
} }
...@@ -235,52 +234,29 @@ dot_all_scops_1 (FILE *file, vec<scop_p> scops) ...@@ -235,52 +234,29 @@ dot_all_scops_1 (FILE *file, vec<scop_p> scops)
dump_flags = tmp_dump_flags; dump_flags = tmp_dump_flags;
} }
/* Display all SCoPs using dotty. */ /* Display SCoP on stderr. */
DEBUG_FUNCTION void
dot_all_scops (vec<scop_p> scops)
{
/* 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 DEBUG_FUNCTION void
dot_scop (scop_p scop) dot_sese (sese_l& scop)
{ {
auto_vec<scop_p, 1> scops; vec<sese_l> scops;
scops.create (1);
if (scop) if (scop)
scops.safe_push (scop); scops.safe_push (scop);
/* When debugging, enable the following code. This cannot be used dot_all_sese (stderr, scops);
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); scops.release ();
fclose (stream); }
x = system ("dotty /tmp/allscops.dot &");
} DEBUG_FUNCTION void
#else dot_cfg ()
dot_all_scops_1 (stderr, scops); {
#endif vec<sese_l> scops;
scops.create (1);
dot_all_sese (stderr, scops);
scops.release ();
} }
/* Return true if BB is empty, contains only DEBUG_INSNs. */ /* Return true if BB is empty, contains only DEBUG_INSNs. */
...@@ -552,9 +528,20 @@ public: ...@@ -552,9 +528,20 @@ public:
static edge get_nearest_pdom_with_single_exit (basic_block dom); 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. /* Merge scops at same loop depth and returns the new sese.
Returns a new SESE when merge was successful, INVALID_SESE otherwise. */ 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) ...@@ -717,9 +704,14 @@ scop_detection::get_nearest_dom_with_single_entry (basic_block dom)
{ {
edge e1 = (*dom->preds)[0]; edge e1 = (*dom->preds)[0];
edge e2 = (*dom->preds)[1]; 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; 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; return e2;
} }
...@@ -738,39 +730,35 @@ scop_detection::get_nearest_dom_with_single_entry (basic_block dom) ...@@ -738,39 +730,35 @@ scop_detection::get_nearest_dom_with_single_entry (basic_block dom)
back-loop the back-edge is not counted. */ back-loop the back-edge is not counted. */
edge 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; return NULL;
if (dom->succs->length () == 2) if (pdom->succs->length () == 2)
{ {
edge e1 = (*dom->succs)[0]; edge e1 = (*pdom->succs)[0];
edge e2 = (*dom->succs)[1]; edge e2 = (*pdom->succs)[1];
if (dominated_by_p (CDI_POST_DOMINATORS, e2->dest, e1->dest)) 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; 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; return e2;
} }
while (dom->succs->length () != 1) while (pdom->succs->length () != 1)
{ {
if (dom->succs->length () < 1) if (pdom->succs->length () < 1)
return NULL; return NULL;
dom = get_immediate_dominator (CDI_POST_DOMINATORS, dom); pdom = get_immediate_dominator (CDI_POST_DOMINATORS, pdom);
if (!dom->succs) if (!pdom->succs)
return NULL; return NULL;
} }
return (*dom->succs)[0];
}
/* Print S to FILE. */
void return (*pdom->succs)[0];
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);
} }
/* Merge scops at same loop depth and returns the new sese. /* 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 ...@@ -815,6 +803,9 @@ scop_detection::merge_sese (sese_l first, sese_l second) const
sese_l combined (entry, exit); 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 /* FIXME: We could iterate to find the dom which dominates pdom, and pdom
which post-dominates dom, until it stabilizes. Also, ENTRY->SRC and which post-dominates dom, until it stabilizes. Also, ENTRY->SRC and
EXIT->DEST should be in the same loop nest. */ EXIT->DEST should be in the same loop nest. */
......
...@@ -465,7 +465,7 @@ extern bool build_poly_scop (scop_p); ...@@ -465,7 +465,7 @@ extern bool build_poly_scop (scop_p);
extern bool graphite_regenerate_ast_isl (scop_p); extern bool graphite_regenerate_ast_isl (scop_p);
extern void build_scops (vec<scop_p> *); extern void build_scops (vec<scop_p> *);
extern void dot_all_scops (vec<scop_p>); extern void dot_all_sese (FILE *, vec<sese_l> &);
extern void dot_scop (scop_p); extern void dot_sese (sese_l &);
extern void dot_cfg ();
#endif #endif
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> 2015-12-04 James Greenhalgh <james.greenhalgh@arm.com>
* gcc.c-torture/compile/20151204.c: New. * gcc.c-torture/compile/20151204.c: New.
......
! { 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
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment