OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [gcc-4.5.1/] [gcc/] [c-omp.c] - Diff between revs 816 and 826

Only display areas with differences | Details | Blame | View Log

Rev 816 Rev 826
/* This file contains routines to construct GNU OpenMP constructs,
/* This file contains routines to construct GNU OpenMP constructs,
   called from parsing in the C and C++ front ends.
   called from parsing in the C and C++ front ends.
 
 
   Copyright (C) 2005, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
   Copyright (C) 2005, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
   Contributed by Richard Henderson <rth@redhat.com>,
   Contributed by Richard Henderson <rth@redhat.com>,
                  Diego Novillo <dnovillo@redhat.com>.
                  Diego Novillo <dnovillo@redhat.com>.
 
 
This file is part of GCC.
This file is part of GCC.
 
 
GCC is free software; you can redistribute it and/or modify it under
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
Software Foundation; either version 3, or (at your option) any later
version.
version.
 
 
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.
for more details.
 
 
You should have received a copy of the GNU General Public License
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3.  If not see
along with GCC; see the file COPYING3.  If not see
<http://www.gnu.org/licenses/>.  */
<http://www.gnu.org/licenses/>.  */
 
 
#include "config.h"
#include "config.h"
#include "system.h"
#include "system.h"
#include "coretypes.h"
#include "coretypes.h"
#include "tm.h"
#include "tm.h"
#include "tree.h"
#include "tree.h"
#include "function.h"
#include "function.h"
#include "c-common.h"
#include "c-common.h"
#include "toplev.h"
#include "toplev.h"
#include "gimple.h"
#include "gimple.h"
#include "bitmap.h"
#include "bitmap.h"
#include "langhooks.h"
#include "langhooks.h"
 
 
 
 
/* Complete a #pragma omp master construct.  STMT is the structured-block
/* Complete a #pragma omp master construct.  STMT is the structured-block
   that follows the pragma.  LOC is the l*/
   that follows the pragma.  LOC is the l*/
 
 
tree
tree
c_finish_omp_master (location_t loc, tree stmt)
c_finish_omp_master (location_t loc, tree stmt)
{
{
  tree t = add_stmt (build1 (OMP_MASTER, void_type_node, stmt));
  tree t = add_stmt (build1 (OMP_MASTER, void_type_node, stmt));
  SET_EXPR_LOCATION (t, loc);
  SET_EXPR_LOCATION (t, loc);
  return t;
  return t;
}
}
 
 
/* Complete a #pragma omp critical construct.  STMT is the structured-block
/* Complete a #pragma omp critical construct.  STMT is the structured-block
   that follows the pragma, NAME is the identifier in the pragma, or null
   that follows the pragma, NAME is the identifier in the pragma, or null
   if it was omitted.  LOC is the location of the #pragma.  */
   if it was omitted.  LOC is the location of the #pragma.  */
 
 
tree
tree
c_finish_omp_critical (location_t loc, tree body, tree name)
c_finish_omp_critical (location_t loc, tree body, tree name)
{
{
  tree stmt = make_node (OMP_CRITICAL);
  tree stmt = make_node (OMP_CRITICAL);
  TREE_TYPE (stmt) = void_type_node;
  TREE_TYPE (stmt) = void_type_node;
  OMP_CRITICAL_BODY (stmt) = body;
  OMP_CRITICAL_BODY (stmt) = body;
  OMP_CRITICAL_NAME (stmt) = name;
  OMP_CRITICAL_NAME (stmt) = name;
  SET_EXPR_LOCATION (stmt, loc);
  SET_EXPR_LOCATION (stmt, loc);
  return add_stmt (stmt);
  return add_stmt (stmt);
}
}
 
 
/* Complete a #pragma omp ordered construct.  STMT is the structured-block
/* Complete a #pragma omp ordered construct.  STMT is the structured-block
   that follows the pragma.  LOC is the location of the #pragma.  */
   that follows the pragma.  LOC is the location of the #pragma.  */
 
 
tree
tree
c_finish_omp_ordered (location_t loc, tree stmt)
c_finish_omp_ordered (location_t loc, tree stmt)
{
{
  tree t = build1 (OMP_ORDERED, void_type_node, stmt);
  tree t = build1 (OMP_ORDERED, void_type_node, stmt);
  SET_EXPR_LOCATION (t, loc);
  SET_EXPR_LOCATION (t, loc);
  return add_stmt (t);
  return add_stmt (t);
}
}
 
 
 
 
/* Complete a #pragma omp barrier construct.  LOC is the location of
/* Complete a #pragma omp barrier construct.  LOC is the location of
   the #pragma.  */
   the #pragma.  */
 
 
void
void
c_finish_omp_barrier (location_t loc)
c_finish_omp_barrier (location_t loc)
{
{
  tree x;
  tree x;
 
 
  x = built_in_decls[BUILT_IN_GOMP_BARRIER];
  x = built_in_decls[BUILT_IN_GOMP_BARRIER];
  x = build_call_expr_loc (loc, x, 0);
  x = build_call_expr_loc (loc, x, 0);
  add_stmt (x);
  add_stmt (x);
}
}
 
 
 
 
/* Complete a #pragma omp taskwait construct.  LOC is the location of the
/* Complete a #pragma omp taskwait construct.  LOC is the location of the
   pragma.  */
   pragma.  */
 
 
void
void
c_finish_omp_taskwait (location_t loc)
c_finish_omp_taskwait (location_t loc)
{
{
  tree x;
  tree x;
 
 
  x = built_in_decls[BUILT_IN_GOMP_TASKWAIT];
  x = built_in_decls[BUILT_IN_GOMP_TASKWAIT];
  x = build_call_expr_loc (loc, x, 0);
  x = build_call_expr_loc (loc, x, 0);
  add_stmt (x);
  add_stmt (x);
}
}
 
 
 
 
/* Complete a #pragma omp atomic construct.  The expression to be
/* Complete a #pragma omp atomic construct.  The expression to be
   implemented atomically is LHS code= RHS.  LOC is the location of
   implemented atomically is LHS code= RHS.  LOC is the location of
   the atomic statement.  The value returned is either error_mark_node
   the atomic statement.  The value returned is either error_mark_node
   (if the construct was erroneous) or an OMP_ATOMIC node which should
   (if the construct was erroneous) or an OMP_ATOMIC node which should
   be added to the current statement tree with add_stmt.*/
   be added to the current statement tree with add_stmt.*/
 
 
tree
tree
c_finish_omp_atomic (location_t loc, enum tree_code code, tree lhs, tree rhs)
c_finish_omp_atomic (location_t loc, enum tree_code code, tree lhs, tree rhs)
{
{
  tree x, type, addr;
  tree x, type, addr;
 
 
  if (lhs == error_mark_node || rhs == error_mark_node)
  if (lhs == error_mark_node || rhs == error_mark_node)
    return error_mark_node;
    return error_mark_node;
 
 
  /* ??? According to one reading of the OpenMP spec, complex type are
  /* ??? According to one reading of the OpenMP spec, complex type are
     supported, but there are no atomic stores for any architecture.
     supported, but there are no atomic stores for any architecture.
     But at least icc 9.0 doesn't support complex types here either.
     But at least icc 9.0 doesn't support complex types here either.
     And lets not even talk about vector types...  */
     And lets not even talk about vector types...  */
  type = TREE_TYPE (lhs);
  type = TREE_TYPE (lhs);
  if (!INTEGRAL_TYPE_P (type)
  if (!INTEGRAL_TYPE_P (type)
      && !POINTER_TYPE_P (type)
      && !POINTER_TYPE_P (type)
      && !SCALAR_FLOAT_TYPE_P (type))
      && !SCALAR_FLOAT_TYPE_P (type))
    {
    {
      error_at (loc, "invalid expression type for %<#pragma omp atomic%>");
      error_at (loc, "invalid expression type for %<#pragma omp atomic%>");
      return error_mark_node;
      return error_mark_node;
    }
    }
 
 
  /* ??? Validate that rhs does not overlap lhs.  */
  /* ??? Validate that rhs does not overlap lhs.  */
 
 
  /* Take and save the address of the lhs.  From then on we'll reference it
  /* Take and save the address of the lhs.  From then on we'll reference it
     via indirection.  */
     via indirection.  */
  addr = build_unary_op (loc, ADDR_EXPR, lhs, 0);
  addr = build_unary_op (loc, ADDR_EXPR, lhs, 0);
  if (addr == error_mark_node)
  if (addr == error_mark_node)
    return error_mark_node;
    return error_mark_node;
  addr = save_expr (addr);
  addr = save_expr (addr);
  if (TREE_CODE (addr) != SAVE_EXPR
  if (TREE_CODE (addr) != SAVE_EXPR
      && (TREE_CODE (addr) != ADDR_EXPR
      && (TREE_CODE (addr) != ADDR_EXPR
          || TREE_CODE (TREE_OPERAND (addr, 0)) != VAR_DECL))
          || TREE_CODE (TREE_OPERAND (addr, 0)) != VAR_DECL))
    {
    {
      /* Make sure LHS is simple enough so that goa_lhs_expr_p can recognize
      /* Make sure LHS is simple enough so that goa_lhs_expr_p can recognize
         it even after unsharing function body.  */
         it even after unsharing function body.  */
      tree var = create_tmp_var_raw (TREE_TYPE (addr), NULL);
      tree var = create_tmp_var_raw (TREE_TYPE (addr), NULL);
      DECL_CONTEXT (var) = current_function_decl;
      DECL_CONTEXT (var) = current_function_decl;
      addr = build4 (TARGET_EXPR, TREE_TYPE (addr), var, addr, NULL, NULL);
      addr = build4 (TARGET_EXPR, TREE_TYPE (addr), var, addr, NULL, NULL);
    }
    }
  lhs = build_indirect_ref (loc, addr, RO_NULL);
  lhs = build_indirect_ref (loc, addr, RO_NULL);
 
 
  /* There are lots of warnings, errors, and conversions that need to happen
  /* There are lots of warnings, errors, and conversions that need to happen
     in the course of interpreting a statement.  Use the normal mechanisms
     in the course of interpreting a statement.  Use the normal mechanisms
     to do this, and then take it apart again.  */
     to do this, and then take it apart again.  */
  x = build_modify_expr (input_location, lhs, NULL_TREE, code,
  x = build_modify_expr (input_location, lhs, NULL_TREE, code,
                         input_location, rhs, NULL_TREE);
                         input_location, rhs, NULL_TREE);
  if (x == error_mark_node)
  if (x == error_mark_node)
    return error_mark_node;
    return error_mark_node;
  gcc_assert (TREE_CODE (x) == MODIFY_EXPR);
  gcc_assert (TREE_CODE (x) == MODIFY_EXPR);
  rhs = TREE_OPERAND (x, 1);
  rhs = TREE_OPERAND (x, 1);
 
 
  /* Punt the actual generation of atomic operations to common code.  */
  /* Punt the actual generation of atomic operations to common code.  */
  x = build2 (OMP_ATOMIC, void_type_node, addr, rhs);
  x = build2 (OMP_ATOMIC, void_type_node, addr, rhs);
  SET_EXPR_LOCATION (x, loc);
  SET_EXPR_LOCATION (x, loc);
  return x;
  return x;
}
}
 
 
 
 
/* Complete a #pragma omp flush construct.  We don't do anything with
/* Complete a #pragma omp flush construct.  We don't do anything with
   the variable list that the syntax allows.  LOC is the location of
   the variable list that the syntax allows.  LOC is the location of
   the #pragma.  */
   the #pragma.  */
 
 
void
void
c_finish_omp_flush (location_t loc)
c_finish_omp_flush (location_t loc)
{
{
  tree x;
  tree x;
 
 
  x = built_in_decls[BUILT_IN_SYNCHRONIZE];
  x = built_in_decls[BUILT_IN_SYNCHRONIZE];
  x = build_call_expr_loc (loc, x, 0);
  x = build_call_expr_loc (loc, x, 0);
  add_stmt (x);
  add_stmt (x);
}
}
 
 
 
 
/* Check and canonicalize #pragma omp for increment expression.
/* Check and canonicalize #pragma omp for increment expression.
   Helper function for c_finish_omp_for.  */
   Helper function for c_finish_omp_for.  */
 
 
static tree
static tree
check_omp_for_incr_expr (location_t loc, tree exp, tree decl)
check_omp_for_incr_expr (location_t loc, tree exp, tree decl)
{
{
  tree t;
  tree t;
 
 
  if (!INTEGRAL_TYPE_P (TREE_TYPE (exp))
  if (!INTEGRAL_TYPE_P (TREE_TYPE (exp))
      || TYPE_PRECISION (TREE_TYPE (exp)) < TYPE_PRECISION (TREE_TYPE (decl)))
      || TYPE_PRECISION (TREE_TYPE (exp)) < TYPE_PRECISION (TREE_TYPE (decl)))
    return error_mark_node;
    return error_mark_node;
 
 
  if (exp == decl)
  if (exp == decl)
    return build_int_cst (TREE_TYPE (exp), 0);
    return build_int_cst (TREE_TYPE (exp), 0);
 
 
  switch (TREE_CODE (exp))
  switch (TREE_CODE (exp))
    {
    {
    CASE_CONVERT:
    CASE_CONVERT:
      t = check_omp_for_incr_expr (loc, TREE_OPERAND (exp, 0), decl);
      t = check_omp_for_incr_expr (loc, TREE_OPERAND (exp, 0), decl);
      if (t != error_mark_node)
      if (t != error_mark_node)
        return fold_convert_loc (loc, TREE_TYPE (exp), t);
        return fold_convert_loc (loc, TREE_TYPE (exp), t);
      break;
      break;
    case MINUS_EXPR:
    case MINUS_EXPR:
      t = check_omp_for_incr_expr (loc, TREE_OPERAND (exp, 0), decl);
      t = check_omp_for_incr_expr (loc, TREE_OPERAND (exp, 0), decl);
      if (t != error_mark_node)
      if (t != error_mark_node)
        return fold_build2_loc (loc, MINUS_EXPR,
        return fold_build2_loc (loc, MINUS_EXPR,
                            TREE_TYPE (exp), t, TREE_OPERAND (exp, 1));
                            TREE_TYPE (exp), t, TREE_OPERAND (exp, 1));
      break;
      break;
    case PLUS_EXPR:
    case PLUS_EXPR:
      t = check_omp_for_incr_expr (loc, TREE_OPERAND (exp, 0), decl);
      t = check_omp_for_incr_expr (loc, TREE_OPERAND (exp, 0), decl);
      if (t != error_mark_node)
      if (t != error_mark_node)
        return fold_build2_loc (loc, PLUS_EXPR,
        return fold_build2_loc (loc, PLUS_EXPR,
                            TREE_TYPE (exp), t, TREE_OPERAND (exp, 1));
                            TREE_TYPE (exp), t, TREE_OPERAND (exp, 1));
      t = check_omp_for_incr_expr (loc, TREE_OPERAND (exp, 1), decl);
      t = check_omp_for_incr_expr (loc, TREE_OPERAND (exp, 1), decl);
      if (t != error_mark_node)
      if (t != error_mark_node)
        return fold_build2_loc (loc, PLUS_EXPR,
        return fold_build2_loc (loc, PLUS_EXPR,
                            TREE_TYPE (exp), TREE_OPERAND (exp, 0), t);
                            TREE_TYPE (exp), TREE_OPERAND (exp, 0), t);
      break;
      break;
    default:
    default:
      break;
      break;
    }
    }
 
 
  return error_mark_node;
  return error_mark_node;
}
}
 
 
/* Validate and emit code for the OpenMP directive #pragma omp for.
/* Validate and emit code for the OpenMP directive #pragma omp for.
   DECLV is a vector of iteration variables, for each collapsed loop.
   DECLV is a vector of iteration variables, for each collapsed loop.
   INITV, CONDV and INCRV are vectors containing initialization
   INITV, CONDV and INCRV are vectors containing initialization
   expressions, controlling predicates and increment expressions.
   expressions, controlling predicates and increment expressions.
   BODY is the body of the loop and PRE_BODY statements that go before
   BODY is the body of the loop and PRE_BODY statements that go before
   the loop.  */
   the loop.  */
 
 
tree
tree
c_finish_omp_for (location_t locus, tree declv, tree initv, tree condv,
c_finish_omp_for (location_t locus, tree declv, tree initv, tree condv,
                  tree incrv, tree body, tree pre_body)
                  tree incrv, tree body, tree pre_body)
{
{
  location_t elocus;
  location_t elocus;
  bool fail = false;
  bool fail = false;
  int i;
  int i;
 
 
  gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (initv));
  gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (initv));
  gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (condv));
  gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (condv));
  gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (incrv));
  gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (incrv));
  for (i = 0; i < TREE_VEC_LENGTH (declv); i++)
  for (i = 0; i < TREE_VEC_LENGTH (declv); i++)
    {
    {
      tree decl = TREE_VEC_ELT (declv, i);
      tree decl = TREE_VEC_ELT (declv, i);
      tree init = TREE_VEC_ELT (initv, i);
      tree init = TREE_VEC_ELT (initv, i);
      tree cond = TREE_VEC_ELT (condv, i);
      tree cond = TREE_VEC_ELT (condv, i);
      tree incr = TREE_VEC_ELT (incrv, i);
      tree incr = TREE_VEC_ELT (incrv, i);
 
 
      elocus = locus;
      elocus = locus;
      if (EXPR_HAS_LOCATION (init))
      if (EXPR_HAS_LOCATION (init))
        elocus = EXPR_LOCATION (init);
        elocus = EXPR_LOCATION (init);
 
 
      /* Validate the iteration variable.  */
      /* Validate the iteration variable.  */
      if (!INTEGRAL_TYPE_P (TREE_TYPE (decl))
      if (!INTEGRAL_TYPE_P (TREE_TYPE (decl))
          && TREE_CODE (TREE_TYPE (decl)) != POINTER_TYPE)
          && TREE_CODE (TREE_TYPE (decl)) != POINTER_TYPE)
        {
        {
          error_at (elocus, "invalid type for iteration variable %qE", decl);
          error_at (elocus, "invalid type for iteration variable %qE", decl);
          fail = true;
          fail = true;
        }
        }
 
 
      /* In the case of "for (int i = 0...)", init will be a decl.  It should
      /* In the case of "for (int i = 0...)", init will be a decl.  It should
         have a DECL_INITIAL that we can turn into an assignment.  */
         have a DECL_INITIAL that we can turn into an assignment.  */
      if (init == decl)
      if (init == decl)
        {
        {
          elocus = DECL_SOURCE_LOCATION (decl);
          elocus = DECL_SOURCE_LOCATION (decl);
 
 
          init = DECL_INITIAL (decl);
          init = DECL_INITIAL (decl);
          if (init == NULL)
          if (init == NULL)
            {
            {
              error_at (elocus, "%qE is not initialized", decl);
              error_at (elocus, "%qE is not initialized", decl);
              init = integer_zero_node;
              init = integer_zero_node;
              fail = true;
              fail = true;
            }
            }
 
 
          init = build_modify_expr (elocus, decl, NULL_TREE, NOP_EXPR,
          init = build_modify_expr (elocus, decl, NULL_TREE, NOP_EXPR,
                                    /* FIXME diagnostics: This should
                                    /* FIXME diagnostics: This should
                                       be the location of the INIT.  */
                                       be the location of the INIT.  */
                                    elocus,
                                    elocus,
                                    init,
                                    init,
                                    NULL_TREE);
                                    NULL_TREE);
        }
        }
      gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
      gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
      gcc_assert (TREE_OPERAND (init, 0) == decl);
      gcc_assert (TREE_OPERAND (init, 0) == decl);
 
 
      if (cond == NULL_TREE)
      if (cond == NULL_TREE)
        {
        {
          error_at (elocus, "missing controlling predicate");
          error_at (elocus, "missing controlling predicate");
          fail = true;
          fail = true;
        }
        }
      else
      else
        {
        {
          bool cond_ok = false;
          bool cond_ok = false;
 
 
          if (EXPR_HAS_LOCATION (cond))
          if (EXPR_HAS_LOCATION (cond))
            elocus = EXPR_LOCATION (cond);
            elocus = EXPR_LOCATION (cond);
 
 
          if (TREE_CODE (cond) == LT_EXPR
          if (TREE_CODE (cond) == LT_EXPR
              || TREE_CODE (cond) == LE_EXPR
              || TREE_CODE (cond) == LE_EXPR
              || TREE_CODE (cond) == GT_EXPR
              || TREE_CODE (cond) == GT_EXPR
              || TREE_CODE (cond) == GE_EXPR
              || TREE_CODE (cond) == GE_EXPR
              || TREE_CODE (cond) == NE_EXPR
              || TREE_CODE (cond) == NE_EXPR
              || TREE_CODE (cond) == EQ_EXPR)
              || TREE_CODE (cond) == EQ_EXPR)
            {
            {
              tree op0 = TREE_OPERAND (cond, 0);
              tree op0 = TREE_OPERAND (cond, 0);
              tree op1 = TREE_OPERAND (cond, 1);
              tree op1 = TREE_OPERAND (cond, 1);
 
 
              /* 2.5.1.  The comparison in the condition is computed in
              /* 2.5.1.  The comparison in the condition is computed in
                 the type of DECL, otherwise the behavior is undefined.
                 the type of DECL, otherwise the behavior is undefined.
 
 
                 For example:
                 For example:
                 long n; int i;
                 long n; int i;
                 i < n;
                 i < n;
 
 
                 according to ISO will be evaluated as:
                 according to ISO will be evaluated as:
                 (long)i < n;
                 (long)i < n;
 
 
                 We want to force:
                 We want to force:
                 i < (int)n;  */
                 i < (int)n;  */
              if (TREE_CODE (op0) == NOP_EXPR
              if (TREE_CODE (op0) == NOP_EXPR
                  && decl == TREE_OPERAND (op0, 0))
                  && decl == TREE_OPERAND (op0, 0))
                {
                {
                  TREE_OPERAND (cond, 0) = TREE_OPERAND (op0, 0);
                  TREE_OPERAND (cond, 0) = TREE_OPERAND (op0, 0);
                  TREE_OPERAND (cond, 1)
                  TREE_OPERAND (cond, 1)
                    = fold_build1_loc (elocus, NOP_EXPR, TREE_TYPE (decl),
                    = fold_build1_loc (elocus, NOP_EXPR, TREE_TYPE (decl),
                                   TREE_OPERAND (cond, 1));
                                   TREE_OPERAND (cond, 1));
                }
                }
              else if (TREE_CODE (op1) == NOP_EXPR
              else if (TREE_CODE (op1) == NOP_EXPR
                       && decl == TREE_OPERAND (op1, 0))
                       && decl == TREE_OPERAND (op1, 0))
                {
                {
                  TREE_OPERAND (cond, 1) = TREE_OPERAND (op1, 0);
                  TREE_OPERAND (cond, 1) = TREE_OPERAND (op1, 0);
                  TREE_OPERAND (cond, 0)
                  TREE_OPERAND (cond, 0)
                    = fold_build1_loc (elocus, NOP_EXPR, TREE_TYPE (decl),
                    = fold_build1_loc (elocus, NOP_EXPR, TREE_TYPE (decl),
                                   TREE_OPERAND (cond, 0));
                                   TREE_OPERAND (cond, 0));
                }
                }
 
 
              if (decl == TREE_OPERAND (cond, 0))
              if (decl == TREE_OPERAND (cond, 0))
                cond_ok = true;
                cond_ok = true;
              else if (decl == TREE_OPERAND (cond, 1))
              else if (decl == TREE_OPERAND (cond, 1))
                {
                {
                  TREE_SET_CODE (cond,
                  TREE_SET_CODE (cond,
                                 swap_tree_comparison (TREE_CODE (cond)));
                                 swap_tree_comparison (TREE_CODE (cond)));
                  TREE_OPERAND (cond, 1) = TREE_OPERAND (cond, 0);
                  TREE_OPERAND (cond, 1) = TREE_OPERAND (cond, 0);
                  TREE_OPERAND (cond, 0) = decl;
                  TREE_OPERAND (cond, 0) = decl;
                  cond_ok = true;
                  cond_ok = true;
                }
                }
 
 
              if (TREE_CODE (cond) == NE_EXPR
              if (TREE_CODE (cond) == NE_EXPR
                  || TREE_CODE (cond) == EQ_EXPR)
                  || TREE_CODE (cond) == EQ_EXPR)
                {
                {
                  if (!INTEGRAL_TYPE_P (TREE_TYPE (decl)))
                  if (!INTEGRAL_TYPE_P (TREE_TYPE (decl)))
                    cond_ok = false;
                    cond_ok = false;
                  else if (operand_equal_p (TREE_OPERAND (cond, 1),
                  else if (operand_equal_p (TREE_OPERAND (cond, 1),
                                            TYPE_MIN_VALUE (TREE_TYPE (decl)),
                                            TYPE_MIN_VALUE (TREE_TYPE (decl)),
                                            0))
                                            0))
                    TREE_SET_CODE (cond, TREE_CODE (cond) == NE_EXPR
                    TREE_SET_CODE (cond, TREE_CODE (cond) == NE_EXPR
                                         ? GT_EXPR : LE_EXPR);
                                         ? GT_EXPR : LE_EXPR);
                  else if (operand_equal_p (TREE_OPERAND (cond, 1),
                  else if (operand_equal_p (TREE_OPERAND (cond, 1),
                                            TYPE_MAX_VALUE (TREE_TYPE (decl)),
                                            TYPE_MAX_VALUE (TREE_TYPE (decl)),
                                            0))
                                            0))
                    TREE_SET_CODE (cond, TREE_CODE (cond) == NE_EXPR
                    TREE_SET_CODE (cond, TREE_CODE (cond) == NE_EXPR
                                         ? LT_EXPR : GE_EXPR);
                                         ? LT_EXPR : GE_EXPR);
                  else
                  else
                    cond_ok = false;
                    cond_ok = false;
                }
                }
            }
            }
 
 
          if (!cond_ok)
          if (!cond_ok)
            {
            {
              error_at (elocus, "invalid controlling predicate");
              error_at (elocus, "invalid controlling predicate");
              fail = true;
              fail = true;
            }
            }
        }
        }
 
 
      if (incr == NULL_TREE)
      if (incr == NULL_TREE)
        {
        {
          error_at (elocus, "missing increment expression");
          error_at (elocus, "missing increment expression");
          fail = true;
          fail = true;
        }
        }
      else
      else
        {
        {
          bool incr_ok = false;
          bool incr_ok = false;
 
 
          if (EXPR_HAS_LOCATION (incr))
          if (EXPR_HAS_LOCATION (incr))
            elocus = EXPR_LOCATION (incr);
            elocus = EXPR_LOCATION (incr);
 
 
          /* Check all the valid increment expressions: v++, v--, ++v, --v,
          /* Check all the valid increment expressions: v++, v--, ++v, --v,
             v = v + incr, v = incr + v and v = v - incr.  */
             v = v + incr, v = incr + v and v = v - incr.  */
          switch (TREE_CODE (incr))
          switch (TREE_CODE (incr))
            {
            {
            case POSTINCREMENT_EXPR:
            case POSTINCREMENT_EXPR:
            case PREINCREMENT_EXPR:
            case PREINCREMENT_EXPR:
            case POSTDECREMENT_EXPR:
            case POSTDECREMENT_EXPR:
            case PREDECREMENT_EXPR:
            case PREDECREMENT_EXPR:
              if (TREE_OPERAND (incr, 0) != decl)
              if (TREE_OPERAND (incr, 0) != decl)
                break;
                break;
 
 
              incr_ok = true;
              incr_ok = true;
              if (POINTER_TYPE_P (TREE_TYPE (decl))
              if (POINTER_TYPE_P (TREE_TYPE (decl))
                  && TREE_OPERAND (incr, 1))
                  && TREE_OPERAND (incr, 1))
                {
                {
                  tree t = fold_convert_loc (elocus,
                  tree t = fold_convert_loc (elocus,
                                             sizetype, TREE_OPERAND (incr, 1));
                                             sizetype, TREE_OPERAND (incr, 1));
 
 
                  if (TREE_CODE (incr) == POSTDECREMENT_EXPR
                  if (TREE_CODE (incr) == POSTDECREMENT_EXPR
                      || TREE_CODE (incr) == PREDECREMENT_EXPR)
                      || TREE_CODE (incr) == PREDECREMENT_EXPR)
                    t = fold_build1_loc (elocus, NEGATE_EXPR, sizetype, t);
                    t = fold_build1_loc (elocus, NEGATE_EXPR, sizetype, t);
                  t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (decl), decl, t);
                  t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (decl), decl, t);
                  incr = build2 (MODIFY_EXPR, void_type_node, decl, t);
                  incr = build2 (MODIFY_EXPR, void_type_node, decl, t);
                }
                }
              break;
              break;
 
 
            case MODIFY_EXPR:
            case MODIFY_EXPR:
              if (TREE_OPERAND (incr, 0) != decl)
              if (TREE_OPERAND (incr, 0) != decl)
                break;
                break;
              if (TREE_OPERAND (incr, 1) == decl)
              if (TREE_OPERAND (incr, 1) == decl)
                break;
                break;
              if (TREE_CODE (TREE_OPERAND (incr, 1)) == PLUS_EXPR
              if (TREE_CODE (TREE_OPERAND (incr, 1)) == PLUS_EXPR
                  && (TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == decl
                  && (TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == decl
                      || TREE_OPERAND (TREE_OPERAND (incr, 1), 1) == decl))
                      || TREE_OPERAND (TREE_OPERAND (incr, 1), 1) == decl))
                incr_ok = true;
                incr_ok = true;
              else if ((TREE_CODE (TREE_OPERAND (incr, 1)) == MINUS_EXPR
              else if ((TREE_CODE (TREE_OPERAND (incr, 1)) == MINUS_EXPR
                        || (TREE_CODE (TREE_OPERAND (incr, 1))
                        || (TREE_CODE (TREE_OPERAND (incr, 1))
                            == POINTER_PLUS_EXPR))
                            == POINTER_PLUS_EXPR))
                       && TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == decl)
                       && TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == decl)
                incr_ok = true;
                incr_ok = true;
              else
              else
                {
                {
                  tree t = check_omp_for_incr_expr (elocus,
                  tree t = check_omp_for_incr_expr (elocus,
                                                    TREE_OPERAND (incr, 1),
                                                    TREE_OPERAND (incr, 1),
                                                    decl);
                                                    decl);
                  if (t != error_mark_node)
                  if (t != error_mark_node)
                    {
                    {
                      incr_ok = true;
                      incr_ok = true;
                      t = build2 (PLUS_EXPR, TREE_TYPE (decl), decl, t);
                      t = build2 (PLUS_EXPR, TREE_TYPE (decl), decl, t);
                      incr = build2 (MODIFY_EXPR, void_type_node, decl, t);
                      incr = build2 (MODIFY_EXPR, void_type_node, decl, t);
                    }
                    }
                }
                }
              break;
              break;
 
 
            default:
            default:
              break;
              break;
            }
            }
          if (!incr_ok)
          if (!incr_ok)
            {
            {
              error_at (elocus, "invalid increment expression");
              error_at (elocus, "invalid increment expression");
              fail = true;
              fail = true;
            }
            }
        }
        }
 
 
      TREE_VEC_ELT (initv, i) = init;
      TREE_VEC_ELT (initv, i) = init;
      TREE_VEC_ELT (incrv, i) = incr;
      TREE_VEC_ELT (incrv, i) = incr;
    }
    }
 
 
  if (fail)
  if (fail)
    return NULL;
    return NULL;
  else
  else
    {
    {
      tree t = make_node (OMP_FOR);
      tree t = make_node (OMP_FOR);
 
 
      TREE_TYPE (t) = void_type_node;
      TREE_TYPE (t) = void_type_node;
      OMP_FOR_INIT (t) = initv;
      OMP_FOR_INIT (t) = initv;
      OMP_FOR_COND (t) = condv;
      OMP_FOR_COND (t) = condv;
      OMP_FOR_INCR (t) = incrv;
      OMP_FOR_INCR (t) = incrv;
      OMP_FOR_BODY (t) = body;
      OMP_FOR_BODY (t) = body;
      OMP_FOR_PRE_BODY (t) = pre_body;
      OMP_FOR_PRE_BODY (t) = pre_body;
 
 
      SET_EXPR_LOCATION (t, locus);
      SET_EXPR_LOCATION (t, locus);
      return add_stmt (t);
      return add_stmt (t);
    }
    }
}
}
 
 
 
 
/* Divide CLAUSES into two lists: those that apply to a parallel
/* Divide CLAUSES into two lists: those that apply to a parallel
   construct, and those that apply to a work-sharing construct.  Place
   construct, and those that apply to a work-sharing construct.  Place
   the results in *PAR_CLAUSES and *WS_CLAUSES respectively.  In
   the results in *PAR_CLAUSES and *WS_CLAUSES respectively.  In
   addition, add a nowait clause to the work-sharing list.  LOC is the
   addition, add a nowait clause to the work-sharing list.  LOC is the
   location of the OMP_PARALLEL*.  */
   location of the OMP_PARALLEL*.  */
 
 
void
void
c_split_parallel_clauses (location_t loc, tree clauses,
c_split_parallel_clauses (location_t loc, tree clauses,
                          tree *par_clauses, tree *ws_clauses)
                          tree *par_clauses, tree *ws_clauses)
{
{
  tree next;
  tree next;
 
 
  *par_clauses = NULL;
  *par_clauses = NULL;
  *ws_clauses = build_omp_clause (loc, OMP_CLAUSE_NOWAIT);
  *ws_clauses = build_omp_clause (loc, OMP_CLAUSE_NOWAIT);
 
 
  for (; clauses ; clauses = next)
  for (; clauses ; clauses = next)
    {
    {
      next = OMP_CLAUSE_CHAIN (clauses);
      next = OMP_CLAUSE_CHAIN (clauses);
 
 
      switch (OMP_CLAUSE_CODE (clauses))
      switch (OMP_CLAUSE_CODE (clauses))
        {
        {
        case OMP_CLAUSE_PRIVATE:
        case OMP_CLAUSE_PRIVATE:
        case OMP_CLAUSE_SHARED:
        case OMP_CLAUSE_SHARED:
        case OMP_CLAUSE_FIRSTPRIVATE:
        case OMP_CLAUSE_FIRSTPRIVATE:
        case OMP_CLAUSE_LASTPRIVATE:
        case OMP_CLAUSE_LASTPRIVATE:
        case OMP_CLAUSE_REDUCTION:
        case OMP_CLAUSE_REDUCTION:
        case OMP_CLAUSE_COPYIN:
        case OMP_CLAUSE_COPYIN:
        case OMP_CLAUSE_IF:
        case OMP_CLAUSE_IF:
        case OMP_CLAUSE_NUM_THREADS:
        case OMP_CLAUSE_NUM_THREADS:
        case OMP_CLAUSE_DEFAULT:
        case OMP_CLAUSE_DEFAULT:
          OMP_CLAUSE_CHAIN (clauses) = *par_clauses;
          OMP_CLAUSE_CHAIN (clauses) = *par_clauses;
          *par_clauses = clauses;
          *par_clauses = clauses;
          break;
          break;
 
 
        case OMP_CLAUSE_SCHEDULE:
        case OMP_CLAUSE_SCHEDULE:
        case OMP_CLAUSE_ORDERED:
        case OMP_CLAUSE_ORDERED:
        case OMP_CLAUSE_COLLAPSE:
        case OMP_CLAUSE_COLLAPSE:
          OMP_CLAUSE_CHAIN (clauses) = *ws_clauses;
          OMP_CLAUSE_CHAIN (clauses) = *ws_clauses;
          *ws_clauses = clauses;
          *ws_clauses = clauses;
          break;
          break;
 
 
        default:
        default:
          gcc_unreachable ();
          gcc_unreachable ();
        }
        }
    }
    }
}
}
 
 
/* True if OpenMP sharing attribute of DECL is predetermined.  */
/* True if OpenMP sharing attribute of DECL is predetermined.  */
 
 
enum omp_clause_default_kind
enum omp_clause_default_kind
c_omp_predetermined_sharing (tree decl)
c_omp_predetermined_sharing (tree decl)
{
{
  /* Variables with const-qualified type having no mutable member
  /* Variables with const-qualified type having no mutable member
     are predetermined shared.  */
     are predetermined shared.  */
  if (TREE_READONLY (decl))
  if (TREE_READONLY (decl))
    return OMP_CLAUSE_DEFAULT_SHARED;
    return OMP_CLAUSE_DEFAULT_SHARED;
 
 
  return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
  return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
}
}
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.