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