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