1169689Skan/* This file contains routines to construct GNU OpenMP constructs,
2169689Skan   called from parsing in the C and C++ front ends.
3169689Skan
4169689Skan   Copyright (C) 2005 Free Software Foundation, Inc.
5169689Skan   Contributed by Richard Henderson <rth@redhat.com>,
6169689Skan		  Diego Novillo <dnovillo@redhat.com>.
7169689Skan
8169689SkanThis file is part of GCC.
9169689Skan
10169689SkanGCC is free software; you can redistribute it and/or modify it under
11169689Skanthe terms of the GNU General Public License as published by the Free
12169689SkanSoftware Foundation; either version 2, or (at your option) any later
13169689Skanversion.
14169689Skan
15169689SkanGCC is distributed in the hope that it will be useful, but WITHOUT ANY
16169689SkanWARRANTY; without even the implied warranty of MERCHANTABILITY or
17169689SkanFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
18169689Skanfor more details.
19169689Skan
20169689SkanYou should have received a copy of the GNU General Public License
21169689Skanalong with GCC; see the file COPYING.  If not, write to the Free
22169689SkanSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
23169689Skan02110-1301, USA.  */
24169689Skan
25169689Skan#include "config.h"
26169689Skan#include "system.h"
27169689Skan#include "coretypes.h"
28169689Skan#include "tm.h"
29169689Skan#include "tree.h"
30169689Skan#include "function.h"
31169689Skan#include "c-common.h"
32169689Skan#include "toplev.h"
33169689Skan#include "tree-gimple.h"
34169689Skan#include "bitmap.h"
35169689Skan#include "langhooks.h"
36169689Skan
37169689Skan
38169689Skan/* Complete a #pragma omp master construct.  STMT is the structured-block
39169689Skan   that follows the pragma.  */
40169689Skan
41169689Skantree
42169689Skanc_finish_omp_master (tree stmt)
43169689Skan{
44169689Skan  return add_stmt (build1 (OMP_MASTER, void_type_node, stmt));
45169689Skan}
46169689Skan
47169689Skan/* Complete a #pragma omp critical construct.  STMT is the structured-block
48169689Skan   that follows the pragma, NAME is the identifier in the pragma, or null
49169689Skan   if it was omitted.  */
50169689Skan
51169689Skantree
52169689Skanc_finish_omp_critical (tree body, tree name)
53169689Skan{
54169689Skan  tree stmt = make_node (OMP_CRITICAL);
55169689Skan  TREE_TYPE (stmt) = void_type_node;
56169689Skan  OMP_CRITICAL_BODY (stmt) = body;
57169689Skan  OMP_CRITICAL_NAME (stmt) = name;
58169689Skan  return add_stmt (stmt);
59169689Skan}
60169689Skan
61169689Skan/* Complete a #pragma omp ordered construct.  STMT is the structured-block
62169689Skan   that follows the pragma.  */
63169689Skan
64169689Skantree
65169689Skanc_finish_omp_ordered (tree stmt)
66169689Skan{
67169689Skan  return add_stmt (build1 (OMP_ORDERED, void_type_node, stmt));
68169689Skan}
69169689Skan
70169689Skan
71169689Skan/* Complete a #pragma omp barrier construct.  */
72169689Skan
73169689Skanvoid
74169689Skanc_finish_omp_barrier (void)
75169689Skan{
76169689Skan  tree x;
77169689Skan
78169689Skan  x = built_in_decls[BUILT_IN_GOMP_BARRIER];
79169689Skan  x = build_function_call_expr (x, NULL);
80169689Skan  add_stmt (x);
81169689Skan}
82169689Skan
83169689Skan
84169689Skan/* Complete a #pragma omp atomic construct.  The expression to be
85169689Skan   implemented atomically is LHS code= RHS.  The value returned is
86169689Skan   either error_mark_node (if the construct was erroneous) or an
87169689Skan   OMP_ATOMIC node which should be added to the current statement tree
88169689Skan   with add_stmt.  */
89169689Skan
90169689Skantree
91169689Skanc_finish_omp_atomic (enum tree_code code, tree lhs, tree rhs)
92169689Skan{
93169689Skan  tree x, type, addr;
94169689Skan
95169689Skan  if (lhs == error_mark_node || rhs == error_mark_node)
96169689Skan    return error_mark_node;
97169689Skan
98169689Skan  /* ??? According to one reading of the OpenMP spec, complex type are
99169689Skan     supported, but there are no atomic stores for any architecture.
100169689Skan     But at least icc 9.0 doesn't support complex types here either.
101169689Skan     And lets not even talk about vector types...  */
102169689Skan  type = TREE_TYPE (lhs);
103169689Skan  if (!INTEGRAL_TYPE_P (type)
104169689Skan      && !POINTER_TYPE_P (type)
105169689Skan      && !SCALAR_FLOAT_TYPE_P (type))
106169689Skan    {
107169689Skan      error ("invalid expression type for %<#pragma omp atomic%>");
108169689Skan      return error_mark_node;
109169689Skan    }
110169689Skan
111169689Skan  /* ??? Validate that rhs does not overlap lhs.  */
112169689Skan
113169689Skan  /* Take and save the address of the lhs.  From then on we'll reference it
114169689Skan     via indirection.  */
115169689Skan  addr = build_unary_op (ADDR_EXPR, lhs, 0);
116169689Skan  if (addr == error_mark_node)
117169689Skan    return error_mark_node;
118169689Skan  addr = save_expr (addr);
119169689Skan  if (TREE_CODE (addr) != SAVE_EXPR
120169689Skan      && (TREE_CODE (addr) != ADDR_EXPR
121169689Skan	  || TREE_CODE (TREE_OPERAND (addr, 0)) != VAR_DECL))
122169689Skan    {
123169689Skan      /* Make sure LHS is simple enough so that goa_lhs_expr_p can recognize
124169689Skan	 it even after unsharing function body.  */
125169689Skan      tree var = create_tmp_var_raw (TREE_TYPE (addr), NULL);
126169689Skan      addr = build4 (TARGET_EXPR, TREE_TYPE (addr), var, addr, NULL, NULL);
127169689Skan    }
128169689Skan  lhs = build_indirect_ref (addr, NULL);
129169689Skan
130169689Skan  /* There are lots of warnings, errors, and conversions that need to happen
131169689Skan     in the course of interpreting a statement.  Use the normal mechanisms
132169689Skan     to do this, and then take it apart again.  */
133169689Skan  x = build_modify_expr (lhs, code, rhs);
134169689Skan  if (x == error_mark_node)
135169689Skan    return error_mark_node;
136169689Skan  gcc_assert (TREE_CODE (x) == MODIFY_EXPR);
137169689Skan  rhs = TREE_OPERAND (x, 1);
138169689Skan
139169689Skan  /* Punt the actual generation of atomic operations to common code.  */
140169689Skan  return build2 (OMP_ATOMIC, void_type_node, addr, rhs);
141169689Skan}
142169689Skan
143169689Skan
144169689Skan/* Complete a #pragma omp flush construct.  We don't do anything with the
145169689Skan   variable list that the syntax allows.  */
146169689Skan
147169689Skanvoid
148169689Skanc_finish_omp_flush (void)
149169689Skan{
150169689Skan  tree x;
151169689Skan
152169689Skan  x = built_in_decls[BUILT_IN_SYNCHRONIZE];
153169689Skan  x = build_function_call_expr (x, NULL);
154169689Skan  add_stmt (x);
155169689Skan}
156169689Skan
157169689Skan
158169689Skan/* Check and canonicalize #pragma omp for increment expression.
159169689Skan   Helper function for c_finish_omp_for.  */
160169689Skan
161169689Skanstatic tree
162169689Skancheck_omp_for_incr_expr (tree exp, tree decl)
163169689Skan{
164169689Skan  tree t;
165169689Skan
166169689Skan  if (!INTEGRAL_TYPE_P (TREE_TYPE (exp))
167169689Skan      || TYPE_PRECISION (TREE_TYPE (exp)) < TYPE_PRECISION (TREE_TYPE (decl)))
168169689Skan    return error_mark_node;
169169689Skan
170169689Skan  if (exp == decl)
171169689Skan    return build_int_cst (TREE_TYPE (exp), 0);
172169689Skan
173169689Skan  switch (TREE_CODE (exp))
174169689Skan    {
175169689Skan    case NOP_EXPR:
176169689Skan      t = check_omp_for_incr_expr (TREE_OPERAND (exp, 0), decl);
177169689Skan      if (t != error_mark_node)
178169689Skan        return fold_convert (TREE_TYPE (exp), t);
179169689Skan      break;
180169689Skan    case MINUS_EXPR:
181169689Skan      t = check_omp_for_incr_expr (TREE_OPERAND (exp, 0), decl);
182169689Skan      if (t != error_mark_node)
183169689Skan        return fold_build2 (MINUS_EXPR, TREE_TYPE (exp), t, TREE_OPERAND (exp, 1));
184169689Skan      break;
185169689Skan    case PLUS_EXPR:
186169689Skan      t = check_omp_for_incr_expr (TREE_OPERAND (exp, 0), decl);
187169689Skan      if (t != error_mark_node)
188169689Skan        return fold_build2 (PLUS_EXPR, TREE_TYPE (exp), t, TREE_OPERAND (exp, 1));
189169689Skan      t = check_omp_for_incr_expr (TREE_OPERAND (exp, 1), decl);
190169689Skan      if (t != error_mark_node)
191169689Skan        return fold_build2 (PLUS_EXPR, TREE_TYPE (exp), TREE_OPERAND (exp, 0), t);
192169689Skan      break;
193169689Skan    default:
194169689Skan      break;
195169689Skan    }
196169689Skan
197169689Skan  return error_mark_node;
198169689Skan}
199169689Skan
200169689Skan/* Validate and emit code for the OpenMP directive #pragma omp for.
201169689Skan   INIT, COND, INCR, BODY and PRE_BODY are the five basic elements
202169689Skan   of the loop (initialization expression, controlling predicate, increment
203169689Skan   expression, body of the loop and statements to go before the loop).
204169689Skan   DECL is the iteration variable.  */
205169689Skan
206169689Skantree
207169689Skanc_finish_omp_for (location_t locus, tree decl, tree init, tree cond,
208169689Skan		  tree incr, tree body, tree pre_body)
209169689Skan{
210169689Skan  location_t elocus = locus;
211169689Skan  bool fail = false;
212169689Skan
213169689Skan  if (EXPR_HAS_LOCATION (init))
214169689Skan    elocus = EXPR_LOCATION (init);
215169689Skan
216169689Skan  /* Validate the iteration variable.  */
217169689Skan  if (!INTEGRAL_TYPE_P (TREE_TYPE (decl)))
218169689Skan    {
219169689Skan      error ("%Hinvalid type for iteration variable %qE", &elocus, decl);
220169689Skan      fail = true;
221169689Skan    }
222169689Skan  if (TYPE_UNSIGNED (TREE_TYPE (decl)))
223169689Skan    warning (0, "%Hiteration variable %qE is unsigned", &elocus, decl);
224169689Skan
225169689Skan  /* In the case of "for (int i = 0...)", init will be a decl.  It should
226169689Skan     have a DECL_INITIAL that we can turn into an assignment.  */
227169689Skan  if (init == decl)
228169689Skan    {
229169689Skan      elocus = DECL_SOURCE_LOCATION (decl);
230169689Skan
231169689Skan      init = DECL_INITIAL (decl);
232169689Skan      if (init == NULL)
233169689Skan	{
234169689Skan	  error ("%H%qE is not initialized", &elocus, decl);
235169689Skan	  init = integer_zero_node;
236169689Skan	  fail = true;
237169689Skan	}
238169689Skan
239169689Skan      init = build_modify_expr (decl, NOP_EXPR, init);
240169689Skan      SET_EXPR_LOCATION (init, elocus);
241169689Skan    }
242169689Skan  gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
243169689Skan  gcc_assert (TREE_OPERAND (init, 0) == decl);
244169689Skan
245169689Skan  if (cond == NULL_TREE)
246169689Skan    {
247169689Skan      error ("%Hmissing controlling predicate", &elocus);
248169689Skan      fail = true;
249169689Skan    }
250169689Skan  else
251169689Skan    {
252169689Skan      bool cond_ok = false;
253169689Skan
254169689Skan      if (EXPR_HAS_LOCATION (cond))
255169689Skan	elocus = EXPR_LOCATION (cond);
256169689Skan
257169689Skan      if (TREE_CODE (cond) == LT_EXPR
258169689Skan	  || TREE_CODE (cond) == LE_EXPR
259169689Skan	  || TREE_CODE (cond) == GT_EXPR
260169689Skan	  || TREE_CODE (cond) == GE_EXPR)
261169689Skan	{
262169689Skan	  tree op0 = TREE_OPERAND (cond, 0);
263169689Skan	  tree op1 = TREE_OPERAND (cond, 1);
264169689Skan
265169689Skan	  /* 2.5.1.  The comparison in the condition is computed in the type
266169689Skan	     of DECL, otherwise the behavior is undefined.
267169689Skan
268169689Skan	     For example:
269169689Skan	     long n; int i;
270169689Skan	     i < n;
271169689Skan
272169689Skan	     according to ISO will be evaluated as:
273169689Skan	     (long)i < n;
274169689Skan
275169689Skan	     We want to force:
276169689Skan	     i < (int)n;  */
277169689Skan	  if (TREE_CODE (op0) == NOP_EXPR
278169689Skan	      && decl == TREE_OPERAND (op0, 0))
279169689Skan	    {
280169689Skan	      TREE_OPERAND (cond, 0) = TREE_OPERAND (op0, 0);
281169689Skan	      TREE_OPERAND (cond, 1) = fold_build1 (NOP_EXPR, TREE_TYPE (decl),
282169689Skan						    TREE_OPERAND (cond, 1));
283169689Skan	    }
284169689Skan	  else if (TREE_CODE (op1) == NOP_EXPR
285169689Skan		   && decl == TREE_OPERAND (op1, 0))
286169689Skan	    {
287169689Skan	      TREE_OPERAND (cond, 1) = TREE_OPERAND (op1, 0);
288169689Skan	      TREE_OPERAND (cond, 0) = fold_build1 (NOP_EXPR, TREE_TYPE (decl),
289169689Skan						    TREE_OPERAND (cond, 0));
290169689Skan	    }
291169689Skan
292169689Skan	  if (decl == TREE_OPERAND (cond, 0))
293169689Skan	    cond_ok = true;
294169689Skan	  else if (decl == TREE_OPERAND (cond, 1))
295169689Skan	    {
296169689Skan	      TREE_SET_CODE (cond, swap_tree_comparison (TREE_CODE (cond)));
297169689Skan	      TREE_OPERAND (cond, 1) = TREE_OPERAND (cond, 0);
298169689Skan	      TREE_OPERAND (cond, 0) = decl;
299169689Skan	      cond_ok = true;
300169689Skan	    }
301169689Skan	}
302169689Skan
303169689Skan      if (!cond_ok)
304169689Skan	{
305169689Skan	  error ("%Hinvalid controlling predicate", &elocus);
306169689Skan	  fail = true;
307169689Skan	}
308169689Skan    }
309169689Skan
310169689Skan  if (incr == NULL_TREE)
311169689Skan    {
312169689Skan      error ("%Hmissing increment expression", &elocus);
313169689Skan      fail = true;
314169689Skan    }
315169689Skan  else
316169689Skan    {
317169689Skan      bool incr_ok = false;
318169689Skan
319169689Skan      if (EXPR_HAS_LOCATION (incr))
320169689Skan	elocus = EXPR_LOCATION (incr);
321169689Skan
322169689Skan      /* Check all the valid increment expressions: v++, v--, ++v, --v,
323169689Skan	 v = v + incr, v = incr + v and v = v - incr.  */
324169689Skan      switch (TREE_CODE (incr))
325169689Skan	{
326169689Skan	case POSTINCREMENT_EXPR:
327169689Skan	case PREINCREMENT_EXPR:
328169689Skan	case POSTDECREMENT_EXPR:
329169689Skan	case PREDECREMENT_EXPR:
330169689Skan	  incr_ok = (TREE_OPERAND (incr, 0) == decl);
331169689Skan	  break;
332169689Skan
333169689Skan	case MODIFY_EXPR:
334169689Skan	  if (TREE_OPERAND (incr, 0) != decl)
335169689Skan	    break;
336169689Skan	  if (TREE_OPERAND (incr, 1) == decl)
337169689Skan	    break;
338169689Skan	  if (TREE_CODE (TREE_OPERAND (incr, 1)) == PLUS_EXPR
339169689Skan	      && (TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == decl
340169689Skan		  || TREE_OPERAND (TREE_OPERAND (incr, 1), 1) == decl))
341169689Skan	    incr_ok = true;
342169689Skan	  else if (TREE_CODE (TREE_OPERAND (incr, 1)) == MINUS_EXPR
343169689Skan		   && TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == decl)
344169689Skan	    incr_ok = true;
345169689Skan	  else
346169689Skan	    {
347169689Skan	      tree t = check_omp_for_incr_expr (TREE_OPERAND (incr, 1), decl);
348169689Skan	      if (t != error_mark_node)
349169689Skan		{
350169689Skan		  incr_ok = true;
351169689Skan		  t = build2 (PLUS_EXPR, TREE_TYPE (decl), decl, t);
352169689Skan		  incr = build2 (MODIFY_EXPR, void_type_node, decl, t);
353169689Skan		}
354169689Skan	    }
355169689Skan	  break;
356169689Skan
357169689Skan	default:
358169689Skan	  break;
359169689Skan	}
360169689Skan      if (!incr_ok)
361169689Skan	{
362169689Skan	  error ("%Hinvalid increment expression", &elocus);
363169689Skan	  fail = true;
364169689Skan	}
365169689Skan    }
366169689Skan
367169689Skan  if (fail)
368169689Skan    return NULL;
369169689Skan  else
370169689Skan    {
371169689Skan      tree t = make_node (OMP_FOR);
372169689Skan
373169689Skan      TREE_TYPE (t) = void_type_node;
374169689Skan      OMP_FOR_INIT (t) = init;
375169689Skan      OMP_FOR_COND (t) = cond;
376169689Skan      OMP_FOR_INCR (t) = incr;
377169689Skan      OMP_FOR_BODY (t) = body;
378169689Skan      OMP_FOR_PRE_BODY (t) = pre_body;
379169689Skan
380169689Skan      SET_EXPR_LOCATION (t, locus);
381169689Skan      return add_stmt (t);
382169689Skan    }
383169689Skan}
384169689Skan
385169689Skan
386169689Skan/* Divide CLAUSES into two lists: those that apply to a parallel construct,
387169689Skan   and those that apply to a work-sharing construct.  Place the results in
388169689Skan   *PAR_CLAUSES and *WS_CLAUSES respectively.  In addition, add a nowait
389169689Skan   clause to the work-sharing list.  */
390169689Skan
391169689Skanvoid
392169689Skanc_split_parallel_clauses (tree clauses, tree *par_clauses, tree *ws_clauses)
393169689Skan{
394169689Skan  tree next;
395169689Skan
396169689Skan  *par_clauses = NULL;
397169689Skan  *ws_clauses = build_omp_clause (OMP_CLAUSE_NOWAIT);
398169689Skan
399169689Skan  for (; clauses ; clauses = next)
400169689Skan    {
401169689Skan      next = OMP_CLAUSE_CHAIN (clauses);
402169689Skan
403169689Skan      switch (OMP_CLAUSE_CODE (clauses))
404169689Skan	{
405169689Skan	case OMP_CLAUSE_PRIVATE:
406169689Skan	case OMP_CLAUSE_SHARED:
407169689Skan	case OMP_CLAUSE_FIRSTPRIVATE:
408169689Skan	case OMP_CLAUSE_LASTPRIVATE:
409169689Skan	case OMP_CLAUSE_REDUCTION:
410169689Skan	case OMP_CLAUSE_COPYIN:
411169689Skan	case OMP_CLAUSE_IF:
412169689Skan	case OMP_CLAUSE_NUM_THREADS:
413169689Skan	case OMP_CLAUSE_DEFAULT:
414169689Skan	  OMP_CLAUSE_CHAIN (clauses) = *par_clauses;
415169689Skan	  *par_clauses = clauses;
416169689Skan	  break;
417169689Skan
418169689Skan	case OMP_CLAUSE_SCHEDULE:
419169689Skan	case OMP_CLAUSE_ORDERED:
420169689Skan	  OMP_CLAUSE_CHAIN (clauses) = *ws_clauses;
421169689Skan	  *ws_clauses = clauses;
422169689Skan	  break;
423169689Skan
424169689Skan	default:
425169689Skan	  gcc_unreachable ();
426169689Skan	}
427169689Skan    }
428169689Skan}
429169689Skan
430169689Skan/* True if OpenMP sharing attribute of DECL is predetermined.  */
431169689Skan
432169689Skanenum omp_clause_default_kind
433169689Skanc_omp_predetermined_sharing (tree decl)
434169689Skan{
435169689Skan  /* Variables with const-qualified type having no mutable member
436169689Skan     are predetermined shared.  */
437169689Skan  if (TREE_READONLY (decl))
438169689Skan    return OMP_CLAUSE_DEFAULT_SHARED;
439169689Skan
440169689Skan  return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
441169689Skan}
442