]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/c-family/c-cilkplus.c
tree-core.h: Include symtab.h.
[thirdparty/gcc.git] / gcc / c-family / c-cilkplus.c
CommitLineData
c02065fc
AH
1/* This file contains routines to construct and validate Cilk Plus
2 constructs within the C and C++ front ends.
3
5624e564 4 Copyright (C) 2013-2015 Free Software Foundation, Inc.
c02065fc
AH
5 Contributed by Aldy Hernandez <aldyh@redhat.com>.
6
7This file is part of GCC.
8
9GCC is free software; you can redistribute it and/or modify it
10under the terms of the GNU General Public License as published by
11the Free Software Foundation; either version 3, or (at your option)
12any later version.
13
14GCC is distributed in the hope that it will be useful, but
15WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17General Public License for more details.
18
19You should have received a copy of the GNU General Public License
20along with GCC; see the file COPYING3. If not see
21<http://www.gnu.org/licenses/>. */
22
23#include "config.h"
24#include "system.h"
25#include "coretypes.h"
40e23961 26#include "alias.h"
c02065fc 27#include "tree.h"
c7131fb2 28#include "options.h"
c02065fc
AH
29#include "c-common.h"
30
31/* Validate the body of a _Cilk_for construct or a <#pragma simd> for
32 loop.
33
34 Returns true if there were no errors, false otherwise. */
35
36bool
37c_check_cilk_loop (location_t loc, tree decl)
38{
39 if (TREE_THIS_VOLATILE (decl))
40 {
41 error_at (loc, "iteration variable cannot be volatile");
42 return false;
43 }
44 return true;
45}
46
47/* Validate and emit code for <#pragma simd> clauses. */
48
49tree
50c_finish_cilk_clauses (tree clauses)
51{
52 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
53 {
54 tree prev = clauses;
55
56 /* If a variable appears in a linear clause it cannot appear in
57 any other OMP clause. */
58 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
59 for (tree c2 = clauses; c2; c2 = OMP_CLAUSE_CHAIN (c2))
60 {
61 if (c == c2)
62 continue;
63 enum omp_clause_code code = OMP_CLAUSE_CODE (c2);
64
65 switch (code)
66 {
67 case OMP_CLAUSE_LINEAR:
68 case OMP_CLAUSE_PRIVATE:
69 case OMP_CLAUSE_FIRSTPRIVATE:
70 case OMP_CLAUSE_LASTPRIVATE:
71 case OMP_CLAUSE_REDUCTION:
72 break;
73
74 case OMP_CLAUSE_SAFELEN:
75 goto next;
76
77 default:
78 gcc_unreachable ();
79 }
80
81 if (OMP_CLAUSE_DECL (c) == OMP_CLAUSE_DECL (c2))
82 {
83 error_at (OMP_CLAUSE_LOCATION (c2),
84 "variable appears in more than one clause");
85 inform (OMP_CLAUSE_LOCATION (c),
86 "other clause defined here");
87 // Remove problematic clauses.
88 OMP_CLAUSE_CHAIN (prev) = OMP_CLAUSE_CHAIN (c2);
89 }
90 next:
91 prev = c2;
92 }
93 }
94 return clauses;
95}
9a771876
JJ
96
97/* Calculate number of iterations of CILK_FOR. */
98
99tree
100cilk_for_number_of_iterations (tree cilk_for)
101{
102 tree t, v, n1, n2, step, type, init, cond, incr, itype;
103 enum tree_code cond_code;
104 location_t loc = EXPR_LOCATION (cilk_for);
105
106 init = TREE_VEC_ELT (OMP_FOR_INIT (cilk_for), 0);
107 v = TREE_OPERAND (init, 0);
108 cond = TREE_VEC_ELT (OMP_FOR_COND (cilk_for), 0);
109 incr = TREE_VEC_ELT (OMP_FOR_INCR (cilk_for), 0);
110 type = TREE_TYPE (v);
111
112 gcc_assert (TREE_CODE (TREE_TYPE (v)) == INTEGER_TYPE
113 || TREE_CODE (TREE_TYPE (v)) == POINTER_TYPE);
114 n1 = TREE_OPERAND (init, 1);
115 cond_code = TREE_CODE (cond);
116 n2 = TREE_OPERAND (cond, 1);
117 switch (cond_code)
118 {
119 case LT_EXPR:
120 case GT_EXPR:
121 case NE_EXPR:
122 break;
123 case LE_EXPR:
124 if (POINTER_TYPE_P (TREE_TYPE (n2)))
125 n2 = fold_build_pointer_plus_hwi_loc (loc, n2, 1);
126 else
127 n2 = fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (n2), n2,
128 build_int_cst (TREE_TYPE (n2), 1));
129 cond_code = LT_EXPR;
130 break;
131 case GE_EXPR:
132 if (POINTER_TYPE_P (TREE_TYPE (n2)))
133 n2 = fold_build_pointer_plus_hwi_loc (loc, n2, -1);
134 else
135 n2 = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (n2), n2,
136 build_int_cst (TREE_TYPE (n2), 1));
137 cond_code = GT_EXPR;
138 break;
139 default:
140 gcc_unreachable ();
141 }
142
143 step = NULL_TREE;
144 switch (TREE_CODE (incr))
145 {
146 case PREINCREMENT_EXPR:
147 case POSTINCREMENT_EXPR:
148 step = build_int_cst (TREE_TYPE (v), 1);
149 break;
150 case PREDECREMENT_EXPR:
151 case POSTDECREMENT_EXPR:
152 step = build_int_cst (TREE_TYPE (v), -1);
153 break;
154 case MODIFY_EXPR:
155 t = TREE_OPERAND (incr, 1);
156 gcc_assert (TREE_OPERAND (t, 0) == v);
157 switch (TREE_CODE (t))
158 {
159 case PLUS_EXPR:
160 step = TREE_OPERAND (t, 1);
161 break;
162 case POINTER_PLUS_EXPR:
163 step = fold_convert (ssizetype, TREE_OPERAND (t, 1));
164 break;
165 case MINUS_EXPR:
166 step = TREE_OPERAND (t, 1);
167 step = fold_build1_loc (loc, NEGATE_EXPR, TREE_TYPE (step), step);
168 break;
169 default:
170 gcc_unreachable ();
171 }
172 break;
173 default:
174 gcc_unreachable ();
175 }
176
177 itype = type;
178 if (POINTER_TYPE_P (itype))
179 itype = signed_type_for (itype);
180 if (cond_code == NE_EXPR)
181 {
182 /* For NE_EXPR, we need to find out if the iterator increases
183 or decreases from whether step is positive or negative. */
184 tree stype = itype;
185 if (TYPE_UNSIGNED (stype))
186 stype = signed_type_for (stype);
187 cond = fold_build2_loc (loc, GE_EXPR, boolean_type_node,
188 fold_convert_loc (loc, stype, step),
189 build_int_cst (stype, 0));
190 t = fold_build3_loc (loc, COND_EXPR, itype, cond,
191 build_int_cst (itype, -1),
192 build_int_cst (itype, 1));
193 }
194 else
195 t = build_int_cst (itype, (cond_code == LT_EXPR ? -1 : 1));
196 t = fold_build2_loc (loc, PLUS_EXPR, itype,
197 fold_convert_loc (loc, itype, step), t);
198 t = fold_build2_loc (loc, PLUS_EXPR, itype, t,
199 fold_convert_loc (loc, itype, n2));
200 t = fold_build2_loc (loc, MINUS_EXPR, itype, t,
201 fold_convert_loc (loc, itype, n1));
202 if (TYPE_UNSIGNED (itype) && cond_code == GT_EXPR)
203 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype,
204 fold_build1_loc (loc, NEGATE_EXPR, itype, t),
205 fold_build1_loc (loc, NEGATE_EXPR, itype,
206 fold_convert_loc (loc, itype,
207 step)));
208 else if (TYPE_UNSIGNED (itype) && cond_code == NE_EXPR)
209 {
210 tree t1
211 = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, t,
212 fold_convert_loc (loc, itype, step));
213 tree t2
214 = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype,
215 fold_build1_loc (loc, NEGATE_EXPR, itype, t),
216 fold_build1_loc (loc, NEGATE_EXPR, itype,
217 fold_convert_loc (loc, itype,
218 step)));
219 t = fold_build3_loc (loc, COND_EXPR, itype, cond, t1, t2);
220 }
221 else
222 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, t,
223 fold_convert_loc (loc, itype, step));
224 cond = fold_build2_loc (loc, cond_code, boolean_type_node, n1, n2);
225 t = fold_build3_loc (loc, COND_EXPR, itype, cond, t,
226 build_int_cst (itype, 0));
227 return t;
228}