summaryrefslogtreecommitdiff
path: root/gcc/c-omp.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/c-omp.c')
-rw-r--r--gcc/c-omp.c315
1 files changed, 182 insertions, 133 deletions
diff --git a/gcc/c-omp.c b/gcc/c-omp.c
index cdca2bcd4a9..1da71d27b9c 100644
--- a/gcc/c-omp.c
+++ b/gcc/c-omp.c
@@ -1,7 +1,7 @@
/* This file contains routines to construct GNU OpenMP constructs,
called from parsing in the C and C++ front ends.
- Copyright (C) 2005, 2007 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2007, 2008 Free Software Foundation, Inc.
Contributed by Richard Henderson <rth@redhat.com>,
Diego Novillo <dnovillo@redhat.com>.
@@ -80,6 +80,19 @@ c_finish_omp_barrier (void)
}
+/* Complete a #pragma omp taskwait construct. */
+
+void
+c_finish_omp_taskwait (void)
+{
+ tree x;
+
+ x = built_in_decls[BUILT_IN_GOMP_TASKWAIT];
+ x = build_call_expr (x, 0);
+ add_stmt (x);
+}
+
+
/* Complete a #pragma omp atomic construct. The expression to be
implemented atomically is LHS code= RHS. The value returned is
either error_mark_node (if the construct was erroneous) or an
@@ -197,170 +210,205 @@ check_omp_for_incr_expr (tree exp, tree decl)
}
/* Validate and emit code for the OpenMP directive #pragma omp for.
- INIT, COND, INCR, BODY and PRE_BODY are the five basic elements
- of the loop (initialization expression, controlling predicate, increment
- expression, body of the loop and statements to go before the loop).
- DECL is the iteration variable. */
+ DECLV is a vector of iteration variables, for each collapsed loop.
+ INITV, CONDV and INCRV are vectors containing initialization
+ expressions, controlling predicates and increment expressions.
+ BODY is the body of the loop and PRE_BODY statements that go before
+ the loop. */
tree
-c_finish_omp_for (location_t locus, tree decl, tree init, tree cond,
- tree incr, tree body, tree pre_body)
+c_finish_omp_for (location_t locus, tree declv, tree initv, tree condv,
+ tree incrv, tree body, tree pre_body)
{
- location_t elocus = locus;
+ location_t elocus;
bool fail = false;
+ int i;
- if (EXPR_HAS_LOCATION (init))
- elocus = EXPR_LOCATION (init);
-
- /* Validate the iteration variable. */
- if (!INTEGRAL_TYPE_P (TREE_TYPE (decl)))
+ gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (initv));
+ gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (condv));
+ gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (incrv));
+ for (i = 0; i < TREE_VEC_LENGTH (declv); i++)
{
- error ("%Hinvalid type for iteration variable %qE", &elocus, decl);
- fail = true;
- }
- if (TYPE_UNSIGNED (TREE_TYPE (decl)))
- warning (0, "%Hiteration variable %qE is unsigned", &elocus, decl);
+ tree decl = TREE_VEC_ELT (declv, i);
+ tree init = TREE_VEC_ELT (initv, i);
+ tree cond = TREE_VEC_ELT (condv, i);
+ tree incr = TREE_VEC_ELT (incrv, i);
+
+ elocus = locus;
+ if (EXPR_HAS_LOCATION (init))
+ elocus = EXPR_LOCATION (init);
+
+ /* Validate the iteration variable. */
+ if (!INTEGRAL_TYPE_P (TREE_TYPE (decl))
+ && TREE_CODE (TREE_TYPE (decl)) != POINTER_TYPE)
+ {
+ error ("%Hinvalid type for iteration variable %qE", &elocus, decl);
+ fail = true;
+ }
- /* In the case of "for (int i = 0...)", init will be a decl. It should
- have a DECL_INITIAL that we can turn into an assignment. */
- if (init == decl)
- {
- elocus = DECL_SOURCE_LOCATION (decl);
+ /* In the case of "for (int i = 0...)", init will be a decl. It should
+ have a DECL_INITIAL that we can turn into an assignment. */
+ if (init == decl)
+ {
+ elocus = DECL_SOURCE_LOCATION (decl);
+
+ init = DECL_INITIAL (decl);
+ if (init == NULL)
+ {
+ error ("%H%qE is not initialized", &elocus, decl);
+ init = integer_zero_node;
+ fail = true;
+ }
- init = DECL_INITIAL (decl);
- if (init == NULL)
+ init = build_modify_expr (decl, NOP_EXPR, init);
+ SET_EXPR_LOCATION (init, elocus);
+ }
+ gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
+ gcc_assert (TREE_OPERAND (init, 0) == decl);
+
+ if (cond == NULL_TREE)
{
- error ("%H%qE is not initialized", &elocus, decl);
- init = integer_zero_node;
+ error ("%Hmissing controlling predicate", &elocus);
fail = true;
}
+ else
+ {
+ bool cond_ok = false;
- init = build_modify_expr (decl, NOP_EXPR, init);
- SET_EXPR_LOCATION (init, elocus);
- }
- gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
- gcc_assert (TREE_OPERAND (init, 0) == decl);
-
- if (cond == NULL_TREE)
- {
- error ("%Hmissing controlling predicate", &elocus);
- fail = true;
- }
- else
- {
- bool cond_ok = false;
+ if (EXPR_HAS_LOCATION (cond))
+ elocus = EXPR_LOCATION (cond);
- if (EXPR_HAS_LOCATION (cond))
- elocus = EXPR_LOCATION (cond);
+ if (TREE_CODE (cond) == LT_EXPR
+ || TREE_CODE (cond) == LE_EXPR
+ || TREE_CODE (cond) == GT_EXPR
+ || TREE_CODE (cond) == GE_EXPR)
+ {
+ tree op0 = TREE_OPERAND (cond, 0);
+ tree op1 = TREE_OPERAND (cond, 1);
- if (TREE_CODE (cond) == LT_EXPR
- || TREE_CODE (cond) == LE_EXPR
- || TREE_CODE (cond) == GT_EXPR
- || TREE_CODE (cond) == GE_EXPR)
- {
- tree op0 = TREE_OPERAND (cond, 0);
- tree op1 = TREE_OPERAND (cond, 1);
+ /* 2.5.1. The comparison in the condition is computed in
+ the type of DECL, otherwise the behavior is undefined.
- /* 2.5.1. The comparison in the condition is computed in the type
- of DECL, otherwise the behavior is undefined.
+ For example:
+ long n; int i;
+ i < n;
- For example:
- long n; int i;
- i < n;
+ according to ISO will be evaluated as:
+ (long)i < n;
- according to ISO will be evaluated as:
- (long)i < n;
+ We want to force:
+ i < (int)n; */
+ if (TREE_CODE (op0) == NOP_EXPR
+ && decl == TREE_OPERAND (op0, 0))
+ {
+ TREE_OPERAND (cond, 0) = TREE_OPERAND (op0, 0);
+ TREE_OPERAND (cond, 1)
+ = fold_build1 (NOP_EXPR, TREE_TYPE (decl),
+ TREE_OPERAND (cond, 1));
+ }
+ else if (TREE_CODE (op1) == NOP_EXPR
+ && decl == TREE_OPERAND (op1, 0))
+ {
+ TREE_OPERAND (cond, 1) = TREE_OPERAND (op1, 0);
+ TREE_OPERAND (cond, 0)
+ = fold_build1 (NOP_EXPR, TREE_TYPE (decl),
+ TREE_OPERAND (cond, 0));
+ }
- We want to force:
- i < (int)n; */
- if (TREE_CODE (op0) == NOP_EXPR
- && decl == TREE_OPERAND (op0, 0))
- {
- TREE_OPERAND (cond, 0) = TREE_OPERAND (op0, 0);
- TREE_OPERAND (cond, 1) = fold_build1 (NOP_EXPR, TREE_TYPE (decl),
- TREE_OPERAND (cond, 1));
- }
- else if (TREE_CODE (op1) == NOP_EXPR
- && decl == TREE_OPERAND (op1, 0))
- {
- TREE_OPERAND (cond, 1) = TREE_OPERAND (op1, 0);
- TREE_OPERAND (cond, 0) = fold_build1 (NOP_EXPR, TREE_TYPE (decl),
- TREE_OPERAND (cond, 0));
+ if (decl == TREE_OPERAND (cond, 0))
+ cond_ok = true;
+ else if (decl == TREE_OPERAND (cond, 1))
+ {
+ TREE_SET_CODE (cond,
+ swap_tree_comparison (TREE_CODE (cond)));
+ TREE_OPERAND (cond, 1) = TREE_OPERAND (cond, 0);
+ TREE_OPERAND (cond, 0) = decl;
+ cond_ok = true;
+ }
}
- if (decl == TREE_OPERAND (cond, 0))
- cond_ok = true;
- else if (decl == TREE_OPERAND (cond, 1))
+ if (!cond_ok)
{
- TREE_SET_CODE (cond, swap_tree_comparison (TREE_CODE (cond)));
- TREE_OPERAND (cond, 1) = TREE_OPERAND (cond, 0);
- TREE_OPERAND (cond, 0) = decl;
- cond_ok = true;
+ error ("%Hinvalid controlling predicate", &elocus);
+ fail = true;
}
}
- if (!cond_ok)
+ if (incr == NULL_TREE)
{
- error ("%Hinvalid controlling predicate", &elocus);
+ error ("%Hmissing increment expression", &elocus);
fail = true;
}
- }
-
- if (incr == NULL_TREE)
- {
- error ("%Hmissing increment expression", &elocus);
- fail = true;
- }
- else
- {
- bool incr_ok = false;
-
- if (EXPR_HAS_LOCATION (incr))
- elocus = EXPR_LOCATION (incr);
-
- /* Check all the valid increment expressions: v++, v--, ++v, --v,
- v = v + incr, v = incr + v and v = v - incr. */
- switch (TREE_CODE (incr))
+ else
{
- case POSTINCREMENT_EXPR:
- case PREINCREMENT_EXPR:
- case POSTDECREMENT_EXPR:
- case PREDECREMENT_EXPR:
- incr_ok = (TREE_OPERAND (incr, 0) == decl);
- break;
+ bool incr_ok = false;
- case MODIFY_EXPR:
- if (TREE_OPERAND (incr, 0) != decl)
- break;
- if (TREE_OPERAND (incr, 1) == decl)
- break;
- if (TREE_CODE (TREE_OPERAND (incr, 1)) == PLUS_EXPR
- && (TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == decl
- || TREE_OPERAND (TREE_OPERAND (incr, 1), 1) == decl))
- incr_ok = true;
- else if (TREE_CODE (TREE_OPERAND (incr, 1)) == MINUS_EXPR
- && TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == decl)
- incr_ok = true;
- else
+ if (EXPR_HAS_LOCATION (incr))
+ elocus = EXPR_LOCATION (incr);
+
+ /* Check all the valid increment expressions: v++, v--, ++v, --v,
+ v = v + incr, v = incr + v and v = v - incr. */
+ switch (TREE_CODE (incr))
{
- tree t = check_omp_for_incr_expr (TREE_OPERAND (incr, 1), decl);
- if (t != error_mark_node)
+ case POSTINCREMENT_EXPR:
+ case PREINCREMENT_EXPR:
+ case POSTDECREMENT_EXPR:
+ case PREDECREMENT_EXPR:
+ if (TREE_OPERAND (incr, 0) != decl)
+ break;
+
+ incr_ok = true;
+ if (POINTER_TYPE_P (TREE_TYPE (decl)))
{
- incr_ok = true;
- t = build2 (PLUS_EXPR, TREE_TYPE (decl), decl, t);
+ tree t = fold_convert (sizetype, TREE_OPERAND (incr, 1));
+
+ if (TREE_CODE (incr) == POSTDECREMENT_EXPR
+ || TREE_CODE (incr) == PREDECREMENT_EXPR)
+ t = fold_build1 (NEGATE_EXPR, sizetype, t);
+ t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (decl), decl, t);
incr = build2 (MODIFY_EXPR, void_type_node, decl, t);
}
- }
- break;
+ break;
+
+ case MODIFY_EXPR:
+ if (TREE_OPERAND (incr, 0) != decl)
+ break;
+ if (TREE_OPERAND (incr, 1) == decl)
+ break;
+ if (TREE_CODE (TREE_OPERAND (incr, 1)) == PLUS_EXPR
+ && (TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == decl
+ || TREE_OPERAND (TREE_OPERAND (incr, 1), 1) == decl))
+ incr_ok = true;
+ else if ((TREE_CODE (TREE_OPERAND (incr, 1)) == MINUS_EXPR
+ || (TREE_CODE (TREE_OPERAND (incr, 1))
+ == POINTER_PLUS_EXPR))
+ && TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == decl)
+ incr_ok = true;
+ else
+ {
+ tree t = check_omp_for_incr_expr (TREE_OPERAND (incr, 1),
+ decl);
+ if (t != error_mark_node)
+ {
+ incr_ok = true;
+ t = build2 (PLUS_EXPR, TREE_TYPE (decl), decl, t);
+ incr = build2 (MODIFY_EXPR, void_type_node, decl, t);
+ }
+ }
+ break;
- default:
- break;
- }
- if (!incr_ok)
- {
- error ("%Hinvalid increment expression", &elocus);
- fail = true;
+ default:
+ break;
+ }
+ if (!incr_ok)
+ {
+ error ("%Hinvalid increment expression", &elocus);
+ fail = true;
+ }
}
+
+ TREE_VEC_ELT (initv, i) = init;
+ TREE_VEC_ELT (incrv, i) = incr;
}
if (fail)
@@ -370,9 +418,9 @@ c_finish_omp_for (location_t locus, tree decl, tree init, tree cond,
tree t = make_node (OMP_FOR);
TREE_TYPE (t) = void_type_node;
- OMP_FOR_INIT (t) = init;
- OMP_FOR_COND (t) = cond;
- OMP_FOR_INCR (t) = incr;
+ OMP_FOR_INIT (t) = initv;
+ OMP_FOR_COND (t) = condv;
+ OMP_FOR_INCR (t) = incrv;
OMP_FOR_BODY (t) = body;
OMP_FOR_PRE_BODY (t) = pre_body;
@@ -416,6 +464,7 @@ c_split_parallel_clauses (tree clauses, tree *par_clauses, tree *ws_clauses)
case OMP_CLAUSE_SCHEDULE:
case OMP_CLAUSE_ORDERED:
+ case OMP_CLAUSE_COLLAPSE:
OMP_CLAUSE_CHAIN (clauses) = *ws_clauses;
*ws_clauses = clauses;
break;