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