aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorTobias Grosser <grosser@fim.uni-passau.de>2009-11-30 22:07:59 +0000
committerTobias Grosser <grosser@gcc.gnu.org>2009-11-30 22:07:59 +0000
commit0dd91484ecd508f2a9f06a65dbba1a5bc08902d0 (patch)
tree706b09e8fc9c4a9701fee8c98393c08fe513b518 /gcc
parentfd2d813d0c2f9119ae3b6298e38e827bfa4fab89 (diff)
downloadgcc-0dd91484ecd508f2a9f06a65dbba1a5bc08902d0.zip
gcc-0dd91484ecd508f2a9f06a65dbba1a5bc08902d0.tar.gz
gcc-0dd91484ecd508f2a9f06a65dbba1a5bc08902d0.tar.bz2
Protect loops that might be executed zero times.
2009-11-23 Tobias Grosser <grosser@fim.uni-passau.de> PR middle-end/42130 * graphite-clast-to-gimple.c (graphite_create_new_loop_guard, translate_clast_for_loop): New. (translate_clast_for): Add a condition around the loop, to do not execute loops with zero iterations. * testsuite/g++.dg/graphite/pr42130.C: New. * testsuite/gcc.dg/graphite/pr35356-2.c: Adapt. From-SVN: r154849
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog.graphite10
-rw-r--r--gcc/graphite-clast-to-gimple.c84
-rw-r--r--gcc/testsuite/g++.dg/graphite/pr42130.C18
-rw-r--r--gcc/testsuite/gcc.dg/graphite/pr35356-2.c16
4 files changed, 124 insertions, 4 deletions
diff --git a/gcc/ChangeLog.graphite b/gcc/ChangeLog.graphite
index c705cbd..863b0be 100644
--- a/gcc/ChangeLog.graphite
+++ b/gcc/ChangeLog.graphite
@@ -1,5 +1,15 @@
2009-11-23 Tobias Grosser <grosser@fim.uni-passau.de>
+ PR middle-end/42130
+ * graphite-clast-to-gimple.c (graphite_create_new_loop_guard,
+ translate_clast_for_loop): New.
+ (translate_clast_for): Add a condition around the loop, to do not
+ execute loops with zero iterations.
+ * testsuite/g++.dg/graphite/pr42130.C: New.
+ * testsuite/gcc.dg/graphite/pr35356-2.c: Adapt.
+
+2009-11-23 Tobias Grosser <grosser@fim.uni-passau.de>
+
* graphite-clast-to-gimple.c (try_mark_loop_parallel): New.
(translate_clast_for, translate_clast_guard, translate_clast, gloog):
Remove context_loop and level.
diff --git a/gcc/graphite-clast-to-gimple.c b/gcc/graphite-clast-to-gimple.c
index 4f45708..3795f6fa 100644
--- a/gcc/graphite-clast-to-gimple.c
+++ b/gcc/graphite-clast-to-gimple.c
@@ -768,8 +768,47 @@ try_mark_loop_parallel (sese region, loop_p loop, htab_t bb_pbb_mapping)
loop->can_be_parallel = true;
}
+static tree gcc_type_for_iv_of_clast_loop (struct clast_for *);
-/* Translates a clast for statement STMT to gimple.
+
+/* Creates a new if region protecting the loop to be executed, if the execution
+ * count is zero (lb > ub). */
+static edge
+graphite_create_new_loop_guard (sese region, edge entry_edge,
+ struct clast_for *stmt,
+ VEC (tree, heap) *newivs,
+ htab_t newivs_index, htab_t params_index)
+{
+ tree cond_expr;
+ edge exit_edge;
+ tree type = gcc_type_for_iv_of_clast_loop (stmt);
+ tree lb = clast_to_gcc_expression (type, stmt->LB, region, newivs,
+ newivs_index, params_index);
+ tree ub = clast_to_gcc_expression (type, stmt->UB, region, newivs,
+ newivs_index, params_index);
+
+ /* XXX: Adding +1 and using LT_EXPR helps with loop latches that have a
+ * loop iteration count of "PARAMETER - 1". For PARAMETER == 0 this becomes
+ * 2^{32|64}, and the condition lb <= ub is true, even if we do not want this.
+ * However lb < ub + 1 is false, as expected.
+ * There might be a problem with cases where ub is 2^32. */
+ tree one;
+ Value gmp_one;
+ value_init (gmp_one);
+ value_set_si (gmp_one, 1);
+ one = gmp_cst_to_tree (type, gmp_one);
+ value_clear (gmp_one);
+
+ ub = fold_build2 (PLUS_EXPR, type, ub, one);
+ cond_expr = fold_build2 (LT_EXPR, boolean_type_node, lb, ub);
+
+ exit_edge = create_empty_if_region_on_edge (entry_edge, cond_expr);
+
+ return exit_edge;
+}
+
+
+/* Create the loop for a clast for statement.
- REGION is the sese region we used to generate the scop.
- NEXT_E is the edge where new generated code should be attached.
@@ -779,7 +818,7 @@ try_mark_loop_parallel (sese region, loop_p loop, htab_t bb_pbb_mapping)
- PARAMS_INDEX connects the cloog parameters with the gimple parameters in
the sese region. */
static edge
-translate_clast_for (sese region, struct clast_for *stmt, edge next_e,
+translate_clast_for_loop (sese region, struct clast_for *stmt, edge next_e,
htab_t rename_map, VEC (tree, heap) **newivs,
htab_t newivs_index, htab_t bb_pbb_mapping,
htab_t params_index)
@@ -802,6 +841,47 @@ translate_clast_for (sese region, struct clast_for *stmt, edge next_e,
return last_e;
}
+/* Translates a clast for statement STMT to gimple. First a guard is created
+ * protecting the loop, if it is executed zero times. In this guard we create
+ * the real loop structure.
+
+ - REGION is the sese region we used to generate the scop.
+ - NEXT_E is the edge where new generated code should be attached.
+ - RENAME_MAP contains a set of tuples of new names associated to
+ the original variables names.
+ - BB_PBB_MAPPING is is a basic_block and it's related poly_bb_p mapping.
+ - PARAMS_INDEX connects the cloog parameters with the gimple parameters in
+ the sese region. */
+static edge
+translate_clast_for (sese region, struct clast_for *stmt, edge next_e,
+ htab_t rename_map, VEC (tree, heap) **newivs,
+ htab_t newivs_index, htab_t bb_pbb_mapping,
+ htab_t params_index)
+{
+ edge last_e = graphite_create_new_loop_guard (region, next_e, stmt, *newivs,
+ newivs_index, params_index);
+
+ edge true_e = get_true_edge_from_guard_bb (next_e->dest);
+ edge false_e = get_false_edge_from_guard_bb (next_e->dest);
+ edge exit_true_e = single_succ_edge (true_e->dest);
+ edge exit_false_e = single_succ_edge (false_e->dest);
+
+ htab_t before_guard = htab_create (10, rename_map_elt_info,
+ eq_rename_map_elts, free);
+ htab_traverse (rename_map, copy_renames, before_guard);
+
+ next_e = translate_clast_for_loop (region, stmt, true_e, rename_map, newivs,
+ newivs_index, bb_pbb_mapping,
+ params_index);
+
+ insert_guard_phis (last_e->src, exit_true_e, exit_false_e,
+ before_guard, rename_map);
+
+ htab_delete (before_guard);
+
+ return last_e;
+}
+
/* Translates a clast guard statement STMT to gimple.
- REGION is the sese region we used to generate the scop.
diff --git a/gcc/testsuite/g++.dg/graphite/pr42130.C b/gcc/testsuite/g++.dg/graphite/pr42130.C
new file mode 100644
index 0000000..92d3bd8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/graphite/pr42130.C
@@ -0,0 +1,18 @@
+/* { dg-options "-O2 -fno-tree-ch" } */
+#include <vector>
+
+using std::vector;
+
+vector<unsigned> & __attribute__((noinline)) foo(unsigned n, unsigned k)
+{
+ vector<unsigned> *vv = new vector<unsigned>(n, 0u);
+ return *vv;
+}
+
+
+int main()
+{
+ foo(0, 1);
+}
+/* { dg-do run } */
+
diff --git a/gcc/testsuite/gcc.dg/graphite/pr35356-2.c b/gcc/testsuite/gcc.dg/graphite/pr35356-2.c
index 5432dee..e5b0213 100644
--- a/gcc/testsuite/gcc.dg/graphite/pr35356-2.c
+++ b/gcc/testsuite/gcc.dg/graphite/pr35356-2.c
@@ -25,8 +25,20 @@ foo (int bar, int n, int k)
| for (i = max(k+1,0); i < n; i++)
| a[i] = i;
+ XXX: At the moment we generate to protect loops that are executed zero times.
+
+ | if (0 < min (n, k) + 1)
+ | for (i = 0; i < min (n, k); i++)
+ | a[i] = i;
+ | if (k >= 0 && k < n)
+ | a[k] = 1;
+ | if (0 < max(n, k) + 1)
+ | for (i = max(k+1,0); i < n; i++)
+ | a[i] = i;
+
*/
-/* { dg-final { scan-tree-dump-times "MIN_EXPR" 1 "graphite" } } */
-/* { dg-final { scan-tree-dump-times "MAX_EXPR" 1 "graphite" } } */
+
+/* { dg-final { scan-tree-dump-times "MIN_EXPR" 2 "graphite" } } */
+/* { dg-final { scan-tree-dump-times "MAX_EXPR" 2 "graphite" } } */
/* { dg-final { cleanup-tree-dump "graphite" } } */