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, 2007, 2008, 2009, 2010, 2011 5 Free Software Foundation, Inc. 6 Contributed by Richard Henderson <rth@redhat.com>, 7 Diego Novillo <dnovillo@redhat.com>. 8 9 This file is part of GCC. 10 11 GCC is free software; you can redistribute it and/or modify it under 12 the terms of the GNU General Public License as published by the Free 13 Software Foundation; either version 3, or (at your option) any later 14 version. 15 16 GCC is distributed in the hope that it will be useful, but WITHOUT ANY 17 WARRANTY; without even the implied warranty of MERCHANTABILITY or 18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 19 for more details. 20 21 You should have received a copy of the GNU General Public License 22 along with GCC; see the file COPYING3. If not see 23 <http://www.gnu.org/licenses/>. */ 24 25 #include "config.h" 26 #include "system.h" 27 #include "coretypes.h" 28 #include "tree.h" 29 #include "c-common.h" 30 #include "gimple.h" /* For create_tmp_var_raw. */ 31 #include "langhooks.h" 32 33 34 /* Complete a #pragma omp master construct. STMT is the structured-block 35 that follows the pragma. LOC is the l*/ 36 37 tree 38 c_finish_omp_master (location_t loc, tree stmt) 39 { 40 tree t = add_stmt (build1 (OMP_MASTER, void_type_node, stmt)); 41 SET_EXPR_LOCATION (t, loc); 42 return t; 43 } 44 45 /* Complete a #pragma omp critical construct. STMT is the structured-block 46 that follows the pragma, NAME is the identifier in the pragma, or null 47 if it was omitted. LOC is the location of the #pragma. */ 48 49 tree 50 c_finish_omp_critical (location_t loc, tree body, tree name) 51 { 52 tree stmt = make_node (OMP_CRITICAL); 53 TREE_TYPE (stmt) = void_type_node; 54 OMP_CRITICAL_BODY (stmt) = body; 55 OMP_CRITICAL_NAME (stmt) = name; 56 SET_EXPR_LOCATION (stmt, loc); 57 return add_stmt (stmt); 58 } 59 60 /* Complete a #pragma omp ordered construct. STMT is the structured-block 61 that follows the pragma. LOC is the location of the #pragma. */ 62 63 tree 64 c_finish_omp_ordered (location_t loc, tree stmt) 65 { 66 tree t = build1 (OMP_ORDERED, void_type_node, stmt); 67 SET_EXPR_LOCATION (t, loc); 68 return add_stmt (t); 69 } 70 71 72 /* Complete a #pragma omp barrier construct. LOC is the location of 73 the #pragma. */ 74 75 void 76 c_finish_omp_barrier (location_t loc) 77 { 78 tree x; 79 80 x = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER); 81 x = build_call_expr_loc (loc, x, 0); 82 add_stmt (x); 83 } 84 85 86 /* Complete a #pragma omp taskwait construct. LOC is the location of the 87 pragma. */ 88 89 void 90 c_finish_omp_taskwait (location_t loc) 91 { 92 tree x; 93 94 x = builtin_decl_explicit (BUILT_IN_GOMP_TASKWAIT); 95 x = build_call_expr_loc (loc, x, 0); 96 add_stmt (x); 97 } 98 99 100 /* Complete a #pragma omp taskyield construct. LOC is the location of the 101 pragma. */ 102 103 void 104 c_finish_omp_taskyield (location_t loc) 105 { 106 tree x; 107 108 x = builtin_decl_explicit (BUILT_IN_GOMP_TASKYIELD); 109 x = build_call_expr_loc (loc, x, 0); 110 add_stmt (x); 111 } 112 113 114 /* Complete a #pragma omp atomic construct. For CODE OMP_ATOMIC 115 the expression to be implemented atomically is LHS opcode= RHS. 116 For OMP_ATOMIC_READ V = LHS, for OMP_ATOMIC_CAPTURE_{NEW,OLD} LHS 117 opcode= RHS with the new or old content of LHS returned. 118 LOC is the location of the atomic statement. The value returned 119 is either error_mark_node (if the construct was erroneous) or an 120 OMP_ATOMIC* node which should be added to the current statement 121 tree with add_stmt. */ 122 123 tree 124 c_finish_omp_atomic (location_t loc, enum tree_code code, 125 enum tree_code opcode, tree lhs, tree rhs, 126 tree v, tree lhs1, tree rhs1) 127 { 128 tree x, type, addr; 129 130 if (lhs == error_mark_node || rhs == error_mark_node 131 || v == error_mark_node || lhs1 == error_mark_node 132 || rhs1 == error_mark_node) 133 return error_mark_node; 134 135 /* ??? According to one reading of the OpenMP spec, complex type are 136 supported, but there are no atomic stores for any architecture. 137 But at least icc 9.0 doesn't support complex types here either. 138 And lets not even talk about vector types... */ 139 type = TREE_TYPE (lhs); 140 if (!INTEGRAL_TYPE_P (type) 141 && !POINTER_TYPE_P (type) 142 && !SCALAR_FLOAT_TYPE_P (type)) 143 { 144 error_at (loc, "invalid expression type for %<#pragma omp atomic%>"); 145 return error_mark_node; 146 } 147 148 /* ??? Validate that rhs does not overlap lhs. */ 149 150 /* Take and save the address of the lhs. From then on we'll reference it 151 via indirection. */ 152 addr = build_unary_op (loc, ADDR_EXPR, lhs, 0); 153 if (addr == error_mark_node) 154 return error_mark_node; 155 addr = save_expr (addr); 156 if (TREE_CODE (addr) != SAVE_EXPR 157 && (TREE_CODE (addr) != ADDR_EXPR 158 || TREE_CODE (TREE_OPERAND (addr, 0)) != VAR_DECL)) 159 { 160 /* Make sure LHS is simple enough so that goa_lhs_expr_p can recognize 161 it even after unsharing function body. */ 162 tree var = create_tmp_var_raw (TREE_TYPE (addr), NULL); 163 DECL_CONTEXT (var) = current_function_decl; 164 addr = build4 (TARGET_EXPR, TREE_TYPE (addr), var, addr, NULL, NULL); 165 } 166 lhs = build_indirect_ref (loc, addr, RO_NULL); 167 168 if (code == OMP_ATOMIC_READ) 169 { 170 x = build1 (OMP_ATOMIC_READ, type, addr); 171 SET_EXPR_LOCATION (x, loc); 172 return build_modify_expr (loc, v, NULL_TREE, NOP_EXPR, 173 loc, x, NULL_TREE); 174 return x; 175 } 176 177 /* There are lots of warnings, errors, and conversions that need to happen 178 in the course of interpreting a statement. Use the normal mechanisms 179 to do this, and then take it apart again. */ 180 x = build_modify_expr (input_location, lhs, NULL_TREE, opcode, 181 input_location, rhs, NULL_TREE); 182 if (x == error_mark_node) 183 return error_mark_node; 184 gcc_assert (TREE_CODE (x) == MODIFY_EXPR); 185 rhs = TREE_OPERAND (x, 1); 186 187 /* Punt the actual generation of atomic operations to common code. */ 188 if (code == OMP_ATOMIC) 189 type = void_type_node; 190 x = build2 (code, type, addr, rhs); 191 SET_EXPR_LOCATION (x, loc); 192 193 /* Generally it is hard to prove lhs1 and lhs are the same memory 194 location, just diagnose different variables. */ 195 if (rhs1 196 && TREE_CODE (rhs1) == VAR_DECL 197 && TREE_CODE (lhs) == VAR_DECL 198 && rhs1 != lhs) 199 { 200 if (code == OMP_ATOMIC) 201 error_at (loc, "%<#pragma omp atomic update%> uses two different variables for memory"); 202 else 203 error_at (loc, "%<#pragma omp atomic capture%> uses two different variables for memory"); 204 return error_mark_node; 205 } 206 207 if (code != OMP_ATOMIC) 208 { 209 /* Generally it is hard to prove lhs1 and lhs are the same memory 210 location, just diagnose different variables. */ 211 if (lhs1 && TREE_CODE (lhs1) == VAR_DECL && TREE_CODE (lhs) == VAR_DECL) 212 { 213 if (lhs1 != lhs) 214 { 215 error_at (loc, "%<#pragma omp atomic capture%> uses two different variables for memory"); 216 return error_mark_node; 217 } 218 } 219 x = build_modify_expr (loc, v, NULL_TREE, NOP_EXPR, 220 loc, x, NULL_TREE); 221 if (rhs1 && rhs1 != lhs) 222 { 223 tree rhs1addr = build_unary_op (loc, ADDR_EXPR, rhs1, 0); 224 if (rhs1addr == error_mark_node) 225 return error_mark_node; 226 x = omit_one_operand_loc (loc, type, x, rhs1addr); 227 } 228 if (lhs1 && lhs1 != lhs) 229 { 230 tree lhs1addr = build_unary_op (loc, ADDR_EXPR, lhs1, 0); 231 if (lhs1addr == error_mark_node) 232 return error_mark_node; 233 if (code == OMP_ATOMIC_CAPTURE_OLD) 234 x = omit_one_operand_loc (loc, type, x, lhs1addr); 235 else 236 { 237 x = save_expr (x); 238 x = omit_two_operands_loc (loc, type, x, x, lhs1addr); 239 } 240 } 241 } 242 else if (rhs1 && rhs1 != lhs) 243 { 244 tree rhs1addr = build_unary_op (loc, ADDR_EXPR, rhs1, 0); 245 if (rhs1addr == error_mark_node) 246 return error_mark_node; 247 x = omit_one_operand_loc (loc, type, x, rhs1addr); 248 } 249 250 return x; 251 } 252 253 254 /* Complete a #pragma omp flush construct. We don't do anything with 255 the variable list that the syntax allows. LOC is the location of 256 the #pragma. */ 257 258 void 259 c_finish_omp_flush (location_t loc) 260 { 261 tree x; 262 263 x = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE); 264 x = build_call_expr_loc (loc, x, 0); 265 add_stmt (x); 266 } 267 268 269 /* Check and canonicalize #pragma omp for increment expression. 270 Helper function for c_finish_omp_for. */ 271 272 static tree 273 check_omp_for_incr_expr (location_t loc, tree exp, tree decl) 274 { 275 tree t; 276 277 if (!INTEGRAL_TYPE_P (TREE_TYPE (exp)) 278 || TYPE_PRECISION (TREE_TYPE (exp)) < TYPE_PRECISION (TREE_TYPE (decl))) 279 return error_mark_node; 280 281 if (exp == decl) 282 return build_int_cst (TREE_TYPE (exp), 0); 283 284 switch (TREE_CODE (exp)) 285 { 286 CASE_CONVERT: 287 t = check_omp_for_incr_expr (loc, TREE_OPERAND (exp, 0), decl); 288 if (t != error_mark_node) 289 return fold_convert_loc (loc, TREE_TYPE (exp), t); 290 break; 291 case MINUS_EXPR: 292 t = check_omp_for_incr_expr (loc, TREE_OPERAND (exp, 0), decl); 293 if (t != error_mark_node) 294 return fold_build2_loc (loc, MINUS_EXPR, 295 TREE_TYPE (exp), t, TREE_OPERAND (exp, 1)); 296 break; 297 case PLUS_EXPR: 298 t = check_omp_for_incr_expr (loc, TREE_OPERAND (exp, 0), decl); 299 if (t != error_mark_node) 300 return fold_build2_loc (loc, PLUS_EXPR, 301 TREE_TYPE (exp), t, TREE_OPERAND (exp, 1)); 302 t = check_omp_for_incr_expr (loc, TREE_OPERAND (exp, 1), decl); 303 if (t != error_mark_node) 304 return fold_build2_loc (loc, PLUS_EXPR, 305 TREE_TYPE (exp), TREE_OPERAND (exp, 0), t); 306 break; 307 case COMPOUND_EXPR: 308 { 309 /* cp_build_modify_expr forces preevaluation of the RHS to make 310 sure that it is evaluated before the lvalue-rvalue conversion 311 is applied to the LHS. Reconstruct the original expression. */ 312 tree op0 = TREE_OPERAND (exp, 0); 313 if (TREE_CODE (op0) == TARGET_EXPR 314 && !VOID_TYPE_P (TREE_TYPE (op0))) 315 { 316 tree op1 = TREE_OPERAND (exp, 1); 317 tree temp = TARGET_EXPR_SLOT (op0); 318 if (TREE_CODE_CLASS (TREE_CODE (op1)) == tcc_binary 319 && TREE_OPERAND (op1, 1) == temp) 320 { 321 op1 = copy_node (op1); 322 TREE_OPERAND (op1, 1) = TARGET_EXPR_INITIAL (op0); 323 return check_omp_for_incr_expr (loc, op1, decl); 324 } 325 } 326 break; 327 } 328 default: 329 break; 330 } 331 332 return error_mark_node; 333 } 334 335 /* Validate and emit code for the OpenMP directive #pragma omp for. 336 DECLV is a vector of iteration variables, for each collapsed loop. 337 INITV, CONDV and INCRV are vectors containing initialization 338 expressions, controlling predicates and increment expressions. 339 BODY is the body of the loop and PRE_BODY statements that go before 340 the loop. */ 341 342 tree 343 c_finish_omp_for (location_t locus, tree declv, tree initv, tree condv, 344 tree incrv, tree body, tree pre_body) 345 { 346 location_t elocus; 347 bool fail = false; 348 int i; 349 350 gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (initv)); 351 gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (condv)); 352 gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (incrv)); 353 for (i = 0; i < TREE_VEC_LENGTH (declv); i++) 354 { 355 tree decl = TREE_VEC_ELT (declv, i); 356 tree init = TREE_VEC_ELT (initv, i); 357 tree cond = TREE_VEC_ELT (condv, i); 358 tree incr = TREE_VEC_ELT (incrv, i); 359 360 elocus = locus; 361 if (EXPR_HAS_LOCATION (init)) 362 elocus = EXPR_LOCATION (init); 363 364 /* Validate the iteration variable. */ 365 if (!INTEGRAL_TYPE_P (TREE_TYPE (decl)) 366 && TREE_CODE (TREE_TYPE (decl)) != POINTER_TYPE) 367 { 368 error_at (elocus, "invalid type for iteration variable %qE", decl); 369 fail = true; 370 } 371 372 /* In the case of "for (int i = 0...)", init will be a decl. It should 373 have a DECL_INITIAL that we can turn into an assignment. */ 374 if (init == decl) 375 { 376 elocus = DECL_SOURCE_LOCATION (decl); 377 378 init = DECL_INITIAL (decl); 379 if (init == NULL) 380 { 381 error_at (elocus, "%qE is not initialized", decl); 382 init = integer_zero_node; 383 fail = true; 384 } 385 386 init = build_modify_expr (elocus, decl, NULL_TREE, NOP_EXPR, 387 /* FIXME diagnostics: This should 388 be the location of the INIT. */ 389 elocus, 390 init, 391 NULL_TREE); 392 } 393 gcc_assert (TREE_CODE (init) == MODIFY_EXPR); 394 gcc_assert (TREE_OPERAND (init, 0) == decl); 395 396 if (cond == NULL_TREE) 397 { 398 error_at (elocus, "missing controlling predicate"); 399 fail = true; 400 } 401 else 402 { 403 bool cond_ok = false; 404 405 if (EXPR_HAS_LOCATION (cond)) 406 elocus = EXPR_LOCATION (cond); 407 408 if (TREE_CODE (cond) == LT_EXPR 409 || TREE_CODE (cond) == LE_EXPR 410 || TREE_CODE (cond) == GT_EXPR 411 || TREE_CODE (cond) == GE_EXPR 412 || TREE_CODE (cond) == NE_EXPR 413 || TREE_CODE (cond) == EQ_EXPR) 414 { 415 tree op0 = TREE_OPERAND (cond, 0); 416 tree op1 = TREE_OPERAND (cond, 1); 417 418 /* 2.5.1. The comparison in the condition is computed in 419 the type of DECL, otherwise the behavior is undefined. 420 421 For example: 422 long n; int i; 423 i < n; 424 425 according to ISO will be evaluated as: 426 (long)i < n; 427 428 We want to force: 429 i < (int)n; */ 430 if (TREE_CODE (op0) == NOP_EXPR 431 && decl == TREE_OPERAND (op0, 0)) 432 { 433 TREE_OPERAND (cond, 0) = TREE_OPERAND (op0, 0); 434 TREE_OPERAND (cond, 1) 435 = fold_build1_loc (elocus, NOP_EXPR, TREE_TYPE (decl), 436 TREE_OPERAND (cond, 1)); 437 } 438 else if (TREE_CODE (op1) == NOP_EXPR 439 && decl == TREE_OPERAND (op1, 0)) 440 { 441 TREE_OPERAND (cond, 1) = TREE_OPERAND (op1, 0); 442 TREE_OPERAND (cond, 0) 443 = fold_build1_loc (elocus, NOP_EXPR, TREE_TYPE (decl), 444 TREE_OPERAND (cond, 0)); 445 } 446 447 if (decl == TREE_OPERAND (cond, 0)) 448 cond_ok = true; 449 else if (decl == TREE_OPERAND (cond, 1)) 450 { 451 TREE_SET_CODE (cond, 452 swap_tree_comparison (TREE_CODE (cond))); 453 TREE_OPERAND (cond, 1) = TREE_OPERAND (cond, 0); 454 TREE_OPERAND (cond, 0) = decl; 455 cond_ok = true; 456 } 457 458 if (TREE_CODE (cond) == NE_EXPR 459 || TREE_CODE (cond) == EQ_EXPR) 460 { 461 if (!INTEGRAL_TYPE_P (TREE_TYPE (decl))) 462 cond_ok = false; 463 else if (operand_equal_p (TREE_OPERAND (cond, 1), 464 TYPE_MIN_VALUE (TREE_TYPE (decl)), 465 0)) 466 TREE_SET_CODE (cond, TREE_CODE (cond) == NE_EXPR 467 ? GT_EXPR : LE_EXPR); 468 else if (operand_equal_p (TREE_OPERAND (cond, 1), 469 TYPE_MAX_VALUE (TREE_TYPE (decl)), 470 0)) 471 TREE_SET_CODE (cond, TREE_CODE (cond) == NE_EXPR 472 ? LT_EXPR : GE_EXPR); 473 else 474 cond_ok = false; 475 } 476 } 477 478 if (!cond_ok) 479 { 480 error_at (elocus, "invalid controlling predicate"); 481 fail = true; 482 } 483 } 484 485 if (incr == NULL_TREE) 486 { 487 error_at (elocus, "missing increment expression"); 488 fail = true; 489 } 490 else 491 { 492 bool incr_ok = false; 493 494 if (EXPR_HAS_LOCATION (incr)) 495 elocus = EXPR_LOCATION (incr); 496 497 /* Check all the valid increment expressions: v++, v--, ++v, --v, 498 v = v + incr, v = incr + v and v = v - incr. */ 499 switch (TREE_CODE (incr)) 500 { 501 case POSTINCREMENT_EXPR: 502 case PREINCREMENT_EXPR: 503 case POSTDECREMENT_EXPR: 504 case PREDECREMENT_EXPR: 505 if (TREE_OPERAND (incr, 0) != decl) 506 break; 507 508 incr_ok = true; 509 if (POINTER_TYPE_P (TREE_TYPE (decl)) 510 && TREE_OPERAND (incr, 1)) 511 { 512 tree t = fold_convert_loc (elocus, 513 sizetype, TREE_OPERAND (incr, 1)); 514 515 if (TREE_CODE (incr) == POSTDECREMENT_EXPR 516 || TREE_CODE (incr) == PREDECREMENT_EXPR) 517 t = fold_build1_loc (elocus, NEGATE_EXPR, sizetype, t); 518 t = fold_build_pointer_plus (decl, t); 519 incr = build2 (MODIFY_EXPR, void_type_node, decl, t); 520 } 521 break; 522 523 case MODIFY_EXPR: 524 if (TREE_OPERAND (incr, 0) != decl) 525 break; 526 if (TREE_OPERAND (incr, 1) == decl) 527 break; 528 if (TREE_CODE (TREE_OPERAND (incr, 1)) == PLUS_EXPR 529 && (TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == decl 530 || TREE_OPERAND (TREE_OPERAND (incr, 1), 1) == decl)) 531 incr_ok = true; 532 else if ((TREE_CODE (TREE_OPERAND (incr, 1)) == MINUS_EXPR 533 || (TREE_CODE (TREE_OPERAND (incr, 1)) 534 == POINTER_PLUS_EXPR)) 535 && TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == decl) 536 incr_ok = true; 537 else 538 { 539 tree t = check_omp_for_incr_expr (elocus, 540 TREE_OPERAND (incr, 1), 541 decl); 542 if (t != error_mark_node) 543 { 544 incr_ok = true; 545 t = build2 (PLUS_EXPR, TREE_TYPE (decl), decl, t); 546 incr = build2 (MODIFY_EXPR, void_type_node, decl, t); 547 } 548 } 549 break; 550 551 default: 552 break; 553 } 554 if (!incr_ok) 555 { 556 error_at (elocus, "invalid increment expression"); 557 fail = true; 558 } 559 } 560 561 TREE_VEC_ELT (initv, i) = init; 562 TREE_VEC_ELT (incrv, i) = incr; 563 } 564 565 if (fail) 566 return NULL; 567 else 568 { 569 tree t = make_node (OMP_FOR); 570 571 TREE_TYPE (t) = void_type_node; 572 OMP_FOR_INIT (t) = initv; 573 OMP_FOR_COND (t) = condv; 574 OMP_FOR_INCR (t) = incrv; 575 OMP_FOR_BODY (t) = body; 576 OMP_FOR_PRE_BODY (t) = pre_body; 577 578 SET_EXPR_LOCATION (t, locus); 579 return add_stmt (t); 580 } 581 } 582 583 584 /* Divide CLAUSES into two lists: those that apply to a parallel 585 construct, and those that apply to a work-sharing construct. Place 586 the results in *PAR_CLAUSES and *WS_CLAUSES respectively. In 587 addition, add a nowait clause to the work-sharing list. LOC is the 588 location of the OMP_PARALLEL*. */ 589 590 void 591 c_split_parallel_clauses (location_t loc, tree clauses, 592 tree *par_clauses, tree *ws_clauses) 593 { 594 tree next; 595 596 *par_clauses = NULL; 597 *ws_clauses = build_omp_clause (loc, OMP_CLAUSE_NOWAIT); 598 599 for (; clauses ; clauses = next) 600 { 601 next = OMP_CLAUSE_CHAIN (clauses); 602 603 switch (OMP_CLAUSE_CODE (clauses)) 604 { 605 case OMP_CLAUSE_PRIVATE: 606 case OMP_CLAUSE_SHARED: 607 case OMP_CLAUSE_FIRSTPRIVATE: 608 case OMP_CLAUSE_LASTPRIVATE: 609 case OMP_CLAUSE_REDUCTION: 610 case OMP_CLAUSE_COPYIN: 611 case OMP_CLAUSE_IF: 612 case OMP_CLAUSE_NUM_THREADS: 613 case OMP_CLAUSE_DEFAULT: 614 OMP_CLAUSE_CHAIN (clauses) = *par_clauses; 615 *par_clauses = clauses; 616 break; 617 618 case OMP_CLAUSE_SCHEDULE: 619 case OMP_CLAUSE_ORDERED: 620 case OMP_CLAUSE_COLLAPSE: 621 OMP_CLAUSE_CHAIN (clauses) = *ws_clauses; 622 *ws_clauses = clauses; 623 break; 624 625 default: 626 gcc_unreachable (); 627 } 628 } 629 } 630 631 /* True if OpenMP sharing attribute of DECL is predetermined. */ 632 633 enum omp_clause_default_kind 634 c_omp_predetermined_sharing (tree decl) 635 { 636 /* Variables with const-qualified type having no mutable member 637 are predetermined shared. */ 638 if (TREE_READONLY (decl)) 639 return OMP_CLAUSE_DEFAULT_SHARED; 640 641 return OMP_CLAUSE_DEFAULT_UNSPECIFIED; 642 } 643