1/* This file contains routines to construct GNU OpenMP constructs, 2 called from parsing in the C and C++ front ends. 3 4 Copyright (C) 2005 Free Software Foundation, Inc. 5 Contributed by Richard Henderson <rth@redhat.com>, 6 Diego Novillo <dnovillo@redhat.com>. 7 8This file is part of GCC. 9 10GCC is free software; you can redistribute it and/or modify it under 11the terms of the GNU General Public License as published by the Free 12Software Foundation; either version 2, or (at your option) any later 13version. 14 15GCC is distributed in the hope that it will be useful, but WITHOUT ANY 16WARRANTY; without even the implied warranty of MERCHANTABILITY or 17FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 18for more details. 19 20You should have received a copy of the GNU General Public License 21along with GCC; see the file COPYING. If not, write to the Free 22Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 2302110-1301, USA. */ 24 25#include "config.h" 26#include "system.h" 27#include "coretypes.h" 28#include "tm.h" 29#include "tree.h" 30#include "function.h" 31#include "c-common.h" 32#include "toplev.h" 33#include "tree-gimple.h" 34#include "bitmap.h" 35#include "langhooks.h" 36 37 38/* Complete a #pragma omp master construct. STMT is the structured-block 39 that follows the pragma. */ 40 41tree 42c_finish_omp_master (tree stmt) 43{ 44 return add_stmt (build1 (OMP_MASTER, void_type_node, stmt)); 45} 46 47/* Complete a #pragma omp critical construct. STMT is the structured-block 48 that follows the pragma, NAME is the identifier in the pragma, or null 49 if it was omitted. */ 50 51tree 52c_finish_omp_critical (tree body, tree name) 53{ 54 tree stmt = make_node (OMP_CRITICAL); 55 TREE_TYPE (stmt) = void_type_node; 56 OMP_CRITICAL_BODY (stmt) = body; 57 OMP_CRITICAL_NAME (stmt) = name; 58 return add_stmt (stmt); 59} 60 61/* Complete a #pragma omp ordered construct. STMT is the structured-block 62 that follows the pragma. */ 63 64tree 65c_finish_omp_ordered (tree stmt) 66{ 67 return add_stmt (build1 (OMP_ORDERED, void_type_node, stmt)); 68} 69 70 71/* Complete a #pragma omp barrier construct. */ 72 73void 74c_finish_omp_barrier (void) 75{ 76 tree x; 77 78 x = built_in_decls[BUILT_IN_GOMP_BARRIER]; 79 x = build_function_call_expr (x, NULL); 80 add_stmt (x); 81} 82 83 84/* Complete a #pragma omp atomic construct. The expression to be 85 implemented atomically is LHS code= RHS. The value returned is 86 either error_mark_node (if the construct was erroneous) or an 87 OMP_ATOMIC node which should be added to the current statement tree 88 with add_stmt. */ 89 90tree 91c_finish_omp_atomic (enum tree_code code, tree lhs, tree rhs) 92{ 93 tree x, type, addr; 94 95 if (lhs == error_mark_node || rhs == error_mark_node) 96 return error_mark_node; 97 98 /* ??? According to one reading of the OpenMP spec, complex type are 99 supported, but there are no atomic stores for any architecture. 100 But at least icc 9.0 doesn't support complex types here either. 101 And lets not even talk about vector types... */ 102 type = TREE_TYPE (lhs); 103 if (!INTEGRAL_TYPE_P (type) 104 && !POINTER_TYPE_P (type) 105 && !SCALAR_FLOAT_TYPE_P (type)) 106 { 107 error ("invalid expression type for %<#pragma omp atomic%>"); 108 return error_mark_node; 109 } 110 111 /* ??? Validate that rhs does not overlap lhs. */ 112 113 /* Take and save the address of the lhs. From then on we'll reference it 114 via indirection. */ 115 addr = build_unary_op (ADDR_EXPR, lhs, 0); 116 if (addr == error_mark_node) 117 return error_mark_node; 118 addr = save_expr (addr); 119 if (TREE_CODE (addr) != SAVE_EXPR 120 && (TREE_CODE (addr) != ADDR_EXPR 121 || TREE_CODE (TREE_OPERAND (addr, 0)) != VAR_DECL)) 122 { 123 /* Make sure LHS is simple enough so that goa_lhs_expr_p can recognize 124 it even after unsharing function body. */ 125 tree var = create_tmp_var_raw (TREE_TYPE (addr), NULL); 126 addr = build4 (TARGET_EXPR, TREE_TYPE (addr), var, addr, NULL, NULL); 127 } 128 lhs = build_indirect_ref (addr, NULL); 129 130 /* There are lots of warnings, errors, and conversions that need to happen 131 in the course of interpreting a statement. Use the normal mechanisms 132 to do this, and then take it apart again. */ 133 x = build_modify_expr (lhs, code, rhs); 134 if (x == error_mark_node) 135 return error_mark_node; 136 gcc_assert (TREE_CODE (x) == MODIFY_EXPR); 137 rhs = TREE_OPERAND (x, 1); 138 139 /* Punt the actual generation of atomic operations to common code. */ 140 return build2 (OMP_ATOMIC, void_type_node, addr, rhs); 141} 142 143 144/* Complete a #pragma omp flush construct. We don't do anything with the 145 variable list that the syntax allows. */ 146 147void 148c_finish_omp_flush (void) 149{ 150 tree x; 151 152 x = built_in_decls[BUILT_IN_SYNCHRONIZE]; 153 x = build_function_call_expr (x, NULL); 154 add_stmt (x); 155} 156 157 158/* Check and canonicalize #pragma omp for increment expression. 159 Helper function for c_finish_omp_for. */ 160 161static tree 162check_omp_for_incr_expr (tree exp, tree decl) 163{ 164 tree t; 165 166 if (!INTEGRAL_TYPE_P (TREE_TYPE (exp)) 167 || TYPE_PRECISION (TREE_TYPE (exp)) < TYPE_PRECISION (TREE_TYPE (decl))) 168 return error_mark_node; 169 170 if (exp == decl) 171 return build_int_cst (TREE_TYPE (exp), 0); 172 173 switch (TREE_CODE (exp)) 174 { 175 case NOP_EXPR: 176 t = check_omp_for_incr_expr (TREE_OPERAND (exp, 0), decl); 177 if (t != error_mark_node) 178 return fold_convert (TREE_TYPE (exp), t); 179 break; 180 case MINUS_EXPR: 181 t = check_omp_for_incr_expr (TREE_OPERAND (exp, 0), decl); 182 if (t != error_mark_node) 183 return fold_build2 (MINUS_EXPR, TREE_TYPE (exp), t, TREE_OPERAND (exp, 1)); 184 break; 185 case PLUS_EXPR: 186 t = check_omp_for_incr_expr (TREE_OPERAND (exp, 0), decl); 187 if (t != error_mark_node) 188 return fold_build2 (PLUS_EXPR, TREE_TYPE (exp), t, TREE_OPERAND (exp, 1)); 189 t = check_omp_for_incr_expr (TREE_OPERAND (exp, 1), decl); 190 if (t != error_mark_node) 191 return fold_build2 (PLUS_EXPR, TREE_TYPE (exp), TREE_OPERAND (exp, 0), t); 192 break; 193 default: 194 break; 195 } 196 197 return error_mark_node; 198} 199 200/* Validate and emit code for the OpenMP directive #pragma omp for. 201 INIT, COND, INCR, BODY and PRE_BODY are the five basic elements 202 of the loop (initialization expression, controlling predicate, increment 203 expression, body of the loop and statements to go before the loop). 204 DECL is the iteration variable. */ 205 206tree 207c_finish_omp_for (location_t locus, tree decl, tree init, tree cond, 208 tree incr, tree body, tree pre_body) 209{ 210 location_t elocus = locus; 211 bool fail = false; 212 213 if (EXPR_HAS_LOCATION (init)) 214 elocus = EXPR_LOCATION (init); 215 216 /* Validate the iteration variable. */ 217 if (!INTEGRAL_TYPE_P (TREE_TYPE (decl))) 218 { 219 error ("%Hinvalid type for iteration variable %qE", &elocus, decl); 220 fail = true; 221 } 222 if (TYPE_UNSIGNED (TREE_TYPE (decl))) 223 warning (0, "%Hiteration variable %qE is unsigned", &elocus, decl); 224 225 /* In the case of "for (int i = 0...)", init will be a decl. It should 226 have a DECL_INITIAL that we can turn into an assignment. */ 227 if (init == decl) 228 { 229 elocus = DECL_SOURCE_LOCATION (decl); 230 231 init = DECL_INITIAL (decl); 232 if (init == NULL) 233 { 234 error ("%H%qE is not initialized", &elocus, decl); 235 init = integer_zero_node; 236 fail = true; 237 } 238 239 init = build_modify_expr (decl, NOP_EXPR, init); 240 SET_EXPR_LOCATION (init, elocus); 241 } 242 gcc_assert (TREE_CODE (init) == MODIFY_EXPR); 243 gcc_assert (TREE_OPERAND (init, 0) == decl); 244 245 if (cond == NULL_TREE) 246 { 247 error ("%Hmissing controlling predicate", &elocus); 248 fail = true; 249 } 250 else 251 { 252 bool cond_ok = false; 253 254 if (EXPR_HAS_LOCATION (cond)) 255 elocus = EXPR_LOCATION (cond); 256 257 if (TREE_CODE (cond) == LT_EXPR 258 || TREE_CODE (cond) == LE_EXPR 259 || TREE_CODE (cond) == GT_EXPR 260 || TREE_CODE (cond) == GE_EXPR) 261 { 262 tree op0 = TREE_OPERAND (cond, 0); 263 tree op1 = TREE_OPERAND (cond, 1); 264 265 /* 2.5.1. The comparison in the condition is computed in the type 266 of DECL, otherwise the behavior is undefined. 267 268 For example: 269 long n; int i; 270 i < n; 271 272 according to ISO will be evaluated as: 273 (long)i < n; 274 275 We want to force: 276 i < (int)n; */ 277 if (TREE_CODE (op0) == NOP_EXPR 278 && decl == TREE_OPERAND (op0, 0)) 279 { 280 TREE_OPERAND (cond, 0) = TREE_OPERAND (op0, 0); 281 TREE_OPERAND (cond, 1) = fold_build1 (NOP_EXPR, TREE_TYPE (decl), 282 TREE_OPERAND (cond, 1)); 283 } 284 else if (TREE_CODE (op1) == NOP_EXPR 285 && decl == TREE_OPERAND (op1, 0)) 286 { 287 TREE_OPERAND (cond, 1) = TREE_OPERAND (op1, 0); 288 TREE_OPERAND (cond, 0) = fold_build1 (NOP_EXPR, TREE_TYPE (decl), 289 TREE_OPERAND (cond, 0)); 290 } 291 292 if (decl == TREE_OPERAND (cond, 0)) 293 cond_ok = true; 294 else if (decl == TREE_OPERAND (cond, 1)) 295 { 296 TREE_SET_CODE (cond, swap_tree_comparison (TREE_CODE (cond))); 297 TREE_OPERAND (cond, 1) = TREE_OPERAND (cond, 0); 298 TREE_OPERAND (cond, 0) = decl; 299 cond_ok = true; 300 } 301 } 302 303 if (!cond_ok) 304 { 305 error ("%Hinvalid controlling predicate", &elocus); 306 fail = true; 307 } 308 } 309 310 if (incr == NULL_TREE) 311 { 312 error ("%Hmissing increment expression", &elocus); 313 fail = true; 314 } 315 else 316 { 317 bool incr_ok = false; 318 319 if (EXPR_HAS_LOCATION (incr)) 320 elocus = EXPR_LOCATION (incr); 321 322 /* Check all the valid increment expressions: v++, v--, ++v, --v, 323 v = v + incr, v = incr + v and v = v - incr. */ 324 switch (TREE_CODE (incr)) 325 { 326 case POSTINCREMENT_EXPR: 327 case PREINCREMENT_EXPR: 328 case POSTDECREMENT_EXPR: 329 case PREDECREMENT_EXPR: 330 incr_ok = (TREE_OPERAND (incr, 0) == decl); 331 break; 332 333 case MODIFY_EXPR: 334 if (TREE_OPERAND (incr, 0) != decl) 335 break; 336 if (TREE_OPERAND (incr, 1) == decl) 337 break; 338 if (TREE_CODE (TREE_OPERAND (incr, 1)) == PLUS_EXPR 339 && (TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == decl 340 || TREE_OPERAND (TREE_OPERAND (incr, 1), 1) == decl)) 341 incr_ok = true; 342 else if (TREE_CODE (TREE_OPERAND (incr, 1)) == MINUS_EXPR 343 && TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == decl) 344 incr_ok = true; 345 else 346 { 347 tree t = check_omp_for_incr_expr (TREE_OPERAND (incr, 1), decl); 348 if (t != error_mark_node) 349 { 350 incr_ok = true; 351 t = build2 (PLUS_EXPR, TREE_TYPE (decl), decl, t); 352 incr = build2 (MODIFY_EXPR, void_type_node, decl, t); 353 } 354 } 355 break; 356 357 default: 358 break; 359 } 360 if (!incr_ok) 361 { 362 error ("%Hinvalid increment expression", &elocus); 363 fail = true; 364 } 365 } 366 367 if (fail) 368 return NULL; 369 else 370 { 371 tree t = make_node (OMP_FOR); 372 373 TREE_TYPE (t) = void_type_node; 374 OMP_FOR_INIT (t) = init; 375 OMP_FOR_COND (t) = cond; 376 OMP_FOR_INCR (t) = incr; 377 OMP_FOR_BODY (t) = body; 378 OMP_FOR_PRE_BODY (t) = pre_body; 379 380 SET_EXPR_LOCATION (t, locus); 381 return add_stmt (t); 382 } 383} 384 385 386/* Divide CLAUSES into two lists: those that apply to a parallel construct, 387 and those that apply to a work-sharing construct. Place the results in 388 *PAR_CLAUSES and *WS_CLAUSES respectively. In addition, add a nowait 389 clause to the work-sharing list. */ 390 391void 392c_split_parallel_clauses (tree clauses, tree *par_clauses, tree *ws_clauses) 393{ 394 tree next; 395 396 *par_clauses = NULL; 397 *ws_clauses = build_omp_clause (OMP_CLAUSE_NOWAIT); 398 399 for (; clauses ; clauses = next) 400 { 401 next = OMP_CLAUSE_CHAIN (clauses); 402 403 switch (OMP_CLAUSE_CODE (clauses)) 404 { 405 case OMP_CLAUSE_PRIVATE: 406 case OMP_CLAUSE_SHARED: 407 case OMP_CLAUSE_FIRSTPRIVATE: 408 case OMP_CLAUSE_LASTPRIVATE: 409 case OMP_CLAUSE_REDUCTION: 410 case OMP_CLAUSE_COPYIN: 411 case OMP_CLAUSE_IF: 412 case OMP_CLAUSE_NUM_THREADS: 413 case OMP_CLAUSE_DEFAULT: 414 OMP_CLAUSE_CHAIN (clauses) = *par_clauses; 415 *par_clauses = clauses; 416 break; 417 418 case OMP_CLAUSE_SCHEDULE: 419 case OMP_CLAUSE_ORDERED: 420 OMP_CLAUSE_CHAIN (clauses) = *ws_clauses; 421 *ws_clauses = clauses; 422 break; 423 424 default: 425 gcc_unreachable (); 426 } 427 } 428} 429 430/* True if OpenMP sharing attribute of DECL is predetermined. */ 431 432enum omp_clause_default_kind 433c_omp_predetermined_sharing (tree decl) 434{ 435 /* Variables with const-qualified type having no mutable member 436 are predetermined shared. */ 437 if (TREE_READONLY (decl)) 438 return OMP_CLAUSE_DEFAULT_SHARED; 439 440 return OMP_CLAUSE_DEFAULT_UNSPECIFIED; 441} 442