c-omp.c revision 169689
11553Srgrimes/* This file contains routines to construct GNU OpenMP constructs,
21553Srgrimes   called from parsing in the C and C++ front ends.
31553Srgrimes
41553Srgrimes   Copyright (C) 2005 Free Software Foundation, Inc.
51553Srgrimes   Contributed by Richard Henderson <rth@redhat.com>,
61553Srgrimes		  Diego Novillo <dnovillo@redhat.com>.
71553Srgrimes
81553SrgrimesThis file is part of GCC.
91553Srgrimes
101553SrgrimesGCC is free software; you can redistribute it and/or modify it under
111553Srgrimesthe terms of the GNU General Public License as published by the Free
121553SrgrimesSoftware Foundation; either version 2, or (at your option) any later
131553Srgrimesversion.
141553Srgrimes
151553SrgrimesGCC is distributed in the hope that it will be useful, but WITHOUT ANY
161553SrgrimesWARRANTY; without even the implied warranty of MERCHANTABILITY or
171553SrgrimesFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
181553Srgrimesfor more details.
191553Srgrimes
201553SrgrimesYou should have received a copy of the GNU General Public License
211553Srgrimesalong with GCC; see the file COPYING.  If not, write to the Free
221553SrgrimesSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
231553Srgrimes02110-1301, USA.  */
241553Srgrimes
251553Srgrimes#include "config.h"
261553Srgrimes#include "system.h"
271553Srgrimes#include "coretypes.h"
281553Srgrimes#include "tm.h"
291553Srgrimes#include "tree.h"
301553Srgrimes#include "function.h"
311553Srgrimes#include "c-common.h"
321553Srgrimes#include "toplev.h"
331553Srgrimes#include "tree-gimple.h"
341553Srgrimes#include "bitmap.h"
3530380Scharnier#include "langhooks.h"
361553Srgrimes
371553Srgrimes
381553Srgrimes/* Complete a #pragma omp master construct.  STMT is the structured-block
391553Srgrimes   that follows the pragma.  */
401553Srgrimes
4130380Scharniertree
421553Srgrimesc_finish_omp_master (tree stmt)
4330380Scharnier{
4430380Scharnier  return add_stmt (build1 (OMP_MASTER, void_type_node, stmt));
4548229Sbrian}
461553Srgrimes
471553Srgrimes/* Complete a #pragma omp critical construct.  STMT is the structured-block
481553Srgrimes   that follows the pragma, NAME is the identifier in the pragma, or null
491553Srgrimes   if it was omitted.  */
501553Srgrimes
511553Srgrimestree
521553Srgrimesc_finish_omp_critical (tree body, tree name)
531553Srgrimes{
541553Srgrimes  tree stmt = make_node (OMP_CRITICAL);
551553Srgrimes  TREE_TYPE (stmt) = void_type_node;
561553Srgrimes  OMP_CRITICAL_BODY (stmt) = body;
571553Srgrimes  OMP_CRITICAL_NAME (stmt) = name;
581553Srgrimes  return add_stmt (stmt);
591553Srgrimes}
601553Srgrimes
611553Srgrimes/* Complete a #pragma omp ordered construct.  STMT is the structured-block
6230380Scharnier   that follows the pragma.  */
631553Srgrimes
641553Srgrimestree
651553Srgrimesc_finish_omp_ordered (tree stmt)
661553Srgrimes{
671553Srgrimes  return add_stmt (build1 (OMP_ORDERED, void_type_node, stmt));
681553Srgrimes}
691553Srgrimes
701553Srgrimes
711553Srgrimes/* Complete a #pragma omp barrier construct.  */
721553Srgrimes
7317829Spstvoid
7418092Speterc_finish_omp_barrier (void)
751553Srgrimes{
761553Srgrimes  tree x;
7710087Sjkh
7810087Sjkh  x = built_in_decls[BUILT_IN_GOMP_BARRIER];
7910087Sjkh  x = build_function_call_expr (x, NULL);
8010087Sjkh  add_stmt (x);
8110087Sjkh}
8210087Sjkh
8310087Sjkh
8410087Sjkh/* Complete a #pragma omp atomic construct.  The expression to be
8510087Sjkh   implemented atomically is LHS code= RHS.  The value returned is
8610087Sjkh   either error_mark_node (if the construct was erroneous) or an
8710087Sjkh   OMP_ATOMIC node which should be added to the current statement tree
8810087Sjkh   with add_stmt.  */
8910087Sjkh
9010087Sjkhtree
9110087Sjkhc_finish_omp_atomic (enum tree_code code, tree lhs, tree rhs)
9210087Sjkh{
9310087Sjkh  tree x, type, addr;
9410087Sjkh
9510087Sjkh  if (lhs == error_mark_node || rhs == error_mark_node)
9610087Sjkh    return error_mark_node;
9710087Sjkh
9810087Sjkh  /* ??? According to one reading of the OpenMP spec, complex type are
9910087Sjkh     supported, but there are no atomic stores for any architecture.
10010087Sjkh     But at least icc 9.0 doesn't support complex types here either.
10110087Sjkh     And lets not even talk about vector types...  */
10210087Sjkh  type = TREE_TYPE (lhs);
10310087Sjkh  if (!INTEGRAL_TYPE_P (type)
10410087Sjkh      && !POINTER_TYPE_P (type)
10510087Sjkh      && !SCALAR_FLOAT_TYPE_P (type))
10617832Spst    {
10717829Spst      error ("invalid expression type for %<#pragma omp atomic%>");
10817829Spst      return error_mark_node;
10910087Sjkh    }
11010087Sjkh
11110087Sjkh  /* ??? Validate that rhs does not overlap lhs.  */
11210087Sjkh
11310087Sjkh  /* Take and save the address of the lhs.  From then on we'll reference it
11410087Sjkh     via indirection.  */
11510087Sjkh  addr = build_unary_op (ADDR_EXPR, lhs, 0);
11610087Sjkh  if (addr == error_mark_node)
11710087Sjkh    return error_mark_node;
11841895Sdes  addr = save_expr (addr);
11942508Ssteve  if (TREE_CODE (addr) != SAVE_EXPR
12047963Sbrian      && (TREE_CODE (addr) != ADDR_EXPR
12110087Sjkh	  || TREE_CODE (TREE_OPERAND (addr, 0)) != VAR_DECL))
12210087Sjkh    {
12310087Sjkh      /* Make sure LHS is simple enough so that goa_lhs_expr_p can recognize
12410087Sjkh	 it even after unsharing function body.  */
12510087Sjkh      tree var = create_tmp_var_raw (TREE_TYPE (addr), NULL);
1261553Srgrimes      addr = build4 (TARGET_EXPR, TREE_TYPE (addr), var, addr, NULL, NULL);
1271553Srgrimes    }
1281553Srgrimes  lhs = build_indirect_ref (addr, NULL);
1291553Srgrimes
1301553Srgrimes  /* There are lots of warnings, errors, and conversions that need to happen
1311553Srgrimes     in the course of interpreting a statement.  Use the normal mechanisms
1321553Srgrimes     to do this, and then take it apart again.  */
1331553Srgrimes  x = build_modify_expr (lhs, code, rhs);
1341553Srgrimes  if (x == error_mark_node)
1351553Srgrimes    return error_mark_node;
1361553Srgrimes  gcc_assert (TREE_CODE (x) == MODIFY_EXPR);
1371553Srgrimes  rhs = TREE_OPERAND (x, 1);
1381553Srgrimes
1391553Srgrimes  /* Punt the actual generation of atomic operations to common code.  */
1401553Srgrimes  return build2 (OMP_ATOMIC, void_type_node, addr, rhs);
1411553Srgrimes}
1421553Srgrimes
1431553Srgrimes
1441553Srgrimes/* Complete a #pragma omp flush construct.  We don't do anything with the
1451553Srgrimes   variable list that the syntax allows.  */
1461553Srgrimes
1471553Srgrimesvoid
1481553Srgrimesc_finish_omp_flush (void)
1491553Srgrimes{
1501553Srgrimes  tree x;
1511553Srgrimes
1521553Srgrimes  x = built_in_decls[BUILT_IN_SYNCHRONIZE];
15317829Spst  x = build_function_call_expr (x, NULL);
1541553Srgrimes  add_stmt (x);
1551553Srgrimes}
1561553Srgrimes
1571553Srgrimes
1581553Srgrimes/* Check and canonicalize #pragma omp for increment expression.
15917829Spst   Helper function for c_finish_omp_for.  */
16030380Scharnier
1611553Srgrimesstatic tree
1621553Srgrimescheck_omp_for_incr_expr (tree exp, tree decl)
16317829Spst{
16417829Spst  tree t;
1651553Srgrimes
1661553Srgrimes  if (!INTEGRAL_TYPE_P (TREE_TYPE (exp))
1671553Srgrimes      || TYPE_PRECISION (TREE_TYPE (exp)) < TYPE_PRECISION (TREE_TYPE (decl)))
1681553Srgrimes    return error_mark_node;
1691553Srgrimes
1701553Srgrimes  if (exp == decl)
17110087Sjkh    return build_int_cst (TREE_TYPE (exp), 0);
1721553Srgrimes
1731553Srgrimes  switch (TREE_CODE (exp))
1741553Srgrimes    {
1751553Srgrimes    case NOP_EXPR:
1761553Srgrimes      t = check_omp_for_incr_expr (TREE_OPERAND (exp, 0), decl);
1771553Srgrimes      if (t != error_mark_node)
1781553Srgrimes        return fold_convert (TREE_TYPE (exp), t);
17917829Spst      break;
18017829Spst    case MINUS_EXPR:
1811553Srgrimes      t = check_omp_for_incr_expr (TREE_OPERAND (exp, 0), decl);
18230380Scharnier      if (t != error_mark_node)
18330380Scharnier        return fold_build2 (MINUS_EXPR, TREE_TYPE (exp), t, TREE_OPERAND (exp, 1));
18417829Spst      break;
18517829Spst    case PLUS_EXPR:
18617829Spst      t = check_omp_for_incr_expr (TREE_OPERAND (exp, 0), decl);
18710087Sjkh      if (t != error_mark_node)
18810087Sjkh        return fold_build2 (PLUS_EXPR, TREE_TYPE (exp), t, TREE_OPERAND (exp, 1));
18910087Sjkh      t = check_omp_for_incr_expr (TREE_OPERAND (exp, 1), decl);
19010087Sjkh      if (t != error_mark_node)
19110087Sjkh        return fold_build2 (PLUS_EXPR, TREE_TYPE (exp), TREE_OPERAND (exp, 0), t);
19210087Sjkh      break;
19310087Sjkh    default:
19430380Scharnier      break;
19530380Scharnier    }
19610087Sjkh
19710087Sjkh  return error_mark_node;
19810087Sjkh}
19910087Sjkh
20041895Sdes/* Validate and emit code for the OpenMP directive #pragma omp for.
20142508Ssteve   INIT, COND, INCR, BODY and PRE_BODY are the five basic elements
20242508Ssteve   of the loop (initialization expression, controlling predicate, increment
20342508Ssteve   expression, body of the loop and statements to go before the loop).
20447963Sbrian   DECL is the iteration variable.  */
20547963Sbrian
20630380Scharniertree
20730380Scharnierc_finish_omp_for (location_t locus, tree decl, tree init, tree cond,
20810087Sjkh		  tree incr, tree body, tree pre_body)
20910087Sjkh{
21030380Scharnier  location_t elocus = locus;
21130380Scharnier  bool fail = false;
2121553Srgrimes
2131553Srgrimes  if (EXPR_HAS_LOCATION (init))
2141553Srgrimes    elocus = EXPR_LOCATION (init);
21510087Sjkh
21610087Sjkh  /* Validate the iteration variable.  */
21710087Sjkh  if (!INTEGRAL_TYPE_P (TREE_TYPE (decl)))
21810087Sjkh    {
21910087Sjkh      error ("%Hinvalid type for iteration variable %qE", &elocus, decl);
22010087Sjkh      fail = true;
22110087Sjkh    }
2221553Srgrimes  if (TYPE_UNSIGNED (TREE_TYPE (decl)))
22310087Sjkh    warning (0, "%Hiteration variable %qE is unsigned", &elocus, decl);
2241553Srgrimes
2251553Srgrimes  /* In the case of "for (int i = 0...)", init will be a decl.  It should
2261553Srgrimes     have a DECL_INITIAL that we can turn into an assignment.  */
2271553Srgrimes  if (init == decl)
2281553Srgrimes    {
2291553Srgrimes      elocus = DECL_SOURCE_LOCATION (decl);
2301553Srgrimes
2311553Srgrimes      init = DECL_INITIAL (decl);
2321553Srgrimes      if (init == NULL)
2331553Srgrimes	{
2341553Srgrimes	  error ("%H%qE is not initialized", &elocus, decl);
23519303Simp	  init = integer_zero_node;
23619303Simp	  fail = true;
2371553Srgrimes	}
2381553Srgrimes
2391553Srgrimes      init = build_modify_expr (decl, NOP_EXPR, init);
2401553Srgrimes      SET_EXPR_LOCATION (init, elocus);
2411553Srgrimes    }
2421553Srgrimes  gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
2431553Srgrimes  gcc_assert (TREE_OPERAND (init, 0) == decl);
2441553Srgrimes
2451553Srgrimes  if (cond == NULL_TREE)
2461553Srgrimes    {
2471553Srgrimes      error ("%Hmissing controlling predicate", &elocus);
2481553Srgrimes      fail = true;
2491553Srgrimes    }
2501553Srgrimes  else
2511553Srgrimes    {
25210087Sjkh      bool cond_ok = false;
2531553Srgrimes
2541553Srgrimes      if (EXPR_HAS_LOCATION (cond))
2551553Srgrimes	elocus = EXPR_LOCATION (cond);
2561553Srgrimes
2571553Srgrimes      if (TREE_CODE (cond) == LT_EXPR
2581553Srgrimes	  || TREE_CODE (cond) == LE_EXPR
25917829Spst	  || TREE_CODE (cond) == GT_EXPR
26018092Speter	  || TREE_CODE (cond) == GE_EXPR)
26117829Spst	{
2621553Srgrimes	  tree op0 = TREE_OPERAND (cond, 0);
2631553Srgrimes	  tree op1 = TREE_OPERAND (cond, 1);
26442508Ssteve
26542508Ssteve	  /* 2.5.1.  The comparison in the condition is computed in the type
26642508Ssteve	     of DECL, otherwise the behavior is undefined.
26742508Ssteve
2681553Srgrimes	     For example:
2691553Srgrimes	     long n; int i;
2701553Srgrimes	     i < n;
2711553Srgrimes
2721553Srgrimes	     according to ISO will be evaluated as:
2731553Srgrimes	     (long)i < n;
2741553Srgrimes
2751553Srgrimes	     We want to force:
2761553Srgrimes	     i < (int)n;  */
2771553Srgrimes	  if (TREE_CODE (op0) == NOP_EXPR
2781553Srgrimes	      && decl == TREE_OPERAND (op0, 0))
27941895Sdes	    {
2801553Srgrimes	      TREE_OPERAND (cond, 0) = TREE_OPERAND (op0, 0);
2811553Srgrimes	      TREE_OPERAND (cond, 1) = fold_build1 (NOP_EXPR, TREE_TYPE (decl),
2821553Srgrimes						    TREE_OPERAND (cond, 1));
2831553Srgrimes	    }
2841553Srgrimes	  else if (TREE_CODE (op1) == NOP_EXPR
2851553Srgrimes		   && decl == TREE_OPERAND (op1, 0))
2861553Srgrimes	    {
2871553Srgrimes	      TREE_OPERAND (cond, 1) = TREE_OPERAND (op1, 0);
28817829Spst	      TREE_OPERAND (cond, 0) = fold_build1 (NOP_EXPR, TREE_TYPE (decl),
2891553Srgrimes						    TREE_OPERAND (cond, 0));
2901553Srgrimes	    }
2911553Srgrimes
2921553Srgrimes	  if (decl == TREE_OPERAND (cond, 0))
29330380Scharnier	    cond_ok = true;
2941553Srgrimes	  else if (decl == TREE_OPERAND (cond, 1))
2951553Srgrimes	    {
2961553Srgrimes	      TREE_SET_CODE (cond, swap_tree_comparison (TREE_CODE (cond)));
2971553Srgrimes	      TREE_OPERAND (cond, 1) = TREE_OPERAND (cond, 0);
2981553Srgrimes	      TREE_OPERAND (cond, 0) = decl;
2991553Srgrimes	      cond_ok = true;
3001553Srgrimes	    }
3011553Srgrimes	}
3021553Srgrimes
3031553Srgrimes      if (!cond_ok)
3041553Srgrimes	{
3051553Srgrimes	  error ("%Hinvalid controlling predicate", &elocus);
3061553Srgrimes	  fail = true;
3071553Srgrimes	}
3081553Srgrimes    }
3091553Srgrimes
3101553Srgrimes  if (incr == NULL_TREE)
3111553Srgrimes    {
3121553Srgrimes      error ("%Hmissing increment expression", &elocus);
3131553Srgrimes      fail = true;
3141553Srgrimes    }
3151553Srgrimes  else
3161553Srgrimes    {
3171553Srgrimes      bool incr_ok = false;
3181553Srgrimes
3191553Srgrimes      if (EXPR_HAS_LOCATION (incr))
3201553Srgrimes	elocus = EXPR_LOCATION (incr);
3211553Srgrimes
3221553Srgrimes      /* Check all the valid increment expressions: v++, v--, ++v, --v,
3231553Srgrimes	 v = v + incr, v = incr + v and v = v - incr.  */
3241553Srgrimes      switch (TREE_CODE (incr))
3251553Srgrimes	{
3261553Srgrimes	case POSTINCREMENT_EXPR:
3271553Srgrimes	case PREINCREMENT_EXPR:
3281553Srgrimes	case POSTDECREMENT_EXPR:
3291553Srgrimes	case PREDECREMENT_EXPR:
33030380Scharnier	  incr_ok = (TREE_OPERAND (incr, 0) == decl);
33130380Scharnier	  break;
33230380Scharnier
33348229Sbrian	case MODIFY_EXPR:
33430380Scharnier	  if (TREE_OPERAND (incr, 0) != decl)
33530380Scharnier	    break;
33617829Spst	  if (TREE_OPERAND (incr, 1) == decl)
33717829Spst	    break;
33817829Spst	  if (TREE_CODE (TREE_OPERAND (incr, 1)) == PLUS_EXPR
33917829Spst	      && (TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == decl
34017829Spst		  || TREE_OPERAND (TREE_OPERAND (incr, 1), 1) == decl))
34117829Spst	    incr_ok = true;
34217829Spst	  else if (TREE_CODE (TREE_OPERAND (incr, 1)) == MINUS_EXPR
34318092Speter		   && TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == decl)
34417829Spst	    incr_ok = true;
34517829Spst	  else
34617829Spst	    {
34717829Spst	      tree t = check_omp_for_incr_expr (TREE_OPERAND (incr, 1), decl);
34817829Spst	      if (t != error_mark_node)
34917829Spst		{
35017829Spst		  incr_ok = true;
35117829Spst		  t = build2 (PLUS_EXPR, TREE_TYPE (decl), decl, t);
35218092Speter		  incr = build2 (MODIFY_EXPR, void_type_node, decl, t);
35318092Speter		}
35418092Speter	    }
35517829Spst	  break;
35617829Spst
35718092Speter	default:
35817829Spst	  break;
35917829Spst	}
3601553Srgrimes      if (!incr_ok)
3611553Srgrimes	{
3621553Srgrimes	  error ("%Hinvalid increment expression", &elocus);
3631553Srgrimes	  fail = true;
3641553Srgrimes	}
3651553Srgrimes    }
36617829Spst
3671553Srgrimes  if (fail)
36817829Spst    return NULL;
3691553Srgrimes  else
3701553Srgrimes    {
3711553Srgrimes      tree t = make_node (OMP_FOR);
37219303Simp
3731553Srgrimes      TREE_TYPE (t) = void_type_node;
3741553Srgrimes      OMP_FOR_INIT (t) = init;
3751553Srgrimes      OMP_FOR_COND (t) = cond;
3761553Srgrimes      OMP_FOR_INCR (t) = incr;
37717829Spst      OMP_FOR_BODY (t) = body;
3781553Srgrimes      OMP_FOR_PRE_BODY (t) = pre_body;
3791553Srgrimes
3801553Srgrimes      SET_EXPR_LOCATION (t, locus);
3811553Srgrimes      return add_stmt (t);
3821553Srgrimes    }
3831553Srgrimes}
3841553Srgrimes
3851553Srgrimes
3861553Srgrimes/* Divide CLAUSES into two lists: those that apply to a parallel construct,
3871553Srgrimes   and those that apply to a work-sharing construct.  Place the results in
3881553Srgrimes   *PAR_CLAUSES and *WS_CLAUSES respectively.  In addition, add a nowait
3891553Srgrimes   clause to the work-sharing list.  */
3901553Srgrimes
3911553Srgrimesvoid
3921553Srgrimesc_split_parallel_clauses (tree clauses, tree *par_clauses, tree *ws_clauses)
3931553Srgrimes{
3941553Srgrimes  tree next;
3951553Srgrimes
3961553Srgrimes  *par_clauses = NULL;
3971553Srgrimes  *ws_clauses = build_omp_clause (OMP_CLAUSE_NOWAIT);
3981553Srgrimes
3991553Srgrimes  for (; clauses ; clauses = next)
4001553Srgrimes    {
4011553Srgrimes      next = OMP_CLAUSE_CHAIN (clauses);
4021553Srgrimes
4031553Srgrimes      switch (OMP_CLAUSE_CODE (clauses))
4041553Srgrimes	{
4051553Srgrimes	case OMP_CLAUSE_PRIVATE:
4061553Srgrimes	case OMP_CLAUSE_SHARED:
4071553Srgrimes	case OMP_CLAUSE_FIRSTPRIVATE:
4081553Srgrimes	case OMP_CLAUSE_LASTPRIVATE:
4091553Srgrimes	case OMP_CLAUSE_REDUCTION:
4101553Srgrimes	case OMP_CLAUSE_COPYIN:
4111553Srgrimes	case OMP_CLAUSE_IF:
4121553Srgrimes	case OMP_CLAUSE_NUM_THREADS:
41330380Scharnier	case OMP_CLAUSE_DEFAULT:
4141553Srgrimes	  OMP_CLAUSE_CHAIN (clauses) = *par_clauses;
4151553Srgrimes	  *par_clauses = clauses;
4161553Srgrimes	  break;
4171553Srgrimes
4181553Srgrimes	case OMP_CLAUSE_SCHEDULE:
4191553Srgrimes	case OMP_CLAUSE_ORDERED:
4201553Srgrimes	  OMP_CLAUSE_CHAIN (clauses) = *ws_clauses;
42130380Scharnier	  *ws_clauses = clauses;
4221553Srgrimes	  break;
4231553Srgrimes
4241553Srgrimes	default:
4251553Srgrimes	  gcc_unreachable ();
4261553Srgrimes	}
4271553Srgrimes    }
4281553Srgrimes}
4291553Srgrimes
4301553Srgrimes/* True if OpenMP sharing attribute of DECL is predetermined.  */
4311553Srgrimes
4321553Srgrimesenum omp_clause_default_kind
4331553Srgrimesc_omp_predetermined_sharing (tree decl)
4341553Srgrimes{
4351553Srgrimes  /* Variables with const-qualified type having no mutable member
4361553Srgrimes     are predetermined shared.  */
4371553Srgrimes  if (TREE_READONLY (decl))
4381553Srgrimes    return OMP_CLAUSE_DEFAULT_SHARED;
4391553Srgrimes
4401553Srgrimes  return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
4411553Srgrimes}
4421553Srgrimes