]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/omp-low.c
Merge from trunk.
[thirdparty/gcc.git] / gcc / omp-low.c
index 7874ff13dd6126783f2e28a4b511eb1875946c3f..17bf1dad0b75dba74f84e0d2e033d629762f147a 100644 (file)
@@ -26,8 +26,14 @@ along with GCC; see the file COPYING3.  If not see
 #include "coretypes.h"
 #include "tm.h"
 #include "tree.h"
+#include "stringpool.h"
+#include "stor-layout.h"
 #include "rtl.h"
 #include "gimple.h"
+#include "gimplify.h"
+#include "gimple-iterator.h"
+#include "gimplify-me.h"
+#include "gimple-walk.h"
 #include "tree-iterator.h"
 #include "tree-inline.h"
 #include "langhooks.h"
@@ -39,6 +45,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "ssa-iterators.h"
 #include "tree-ssanames.h"
 #include "tree-into-ssa.h"
+#include "expr.h"
 #include "tree-dfa.h"
 #include "tree-ssa.h"
 #include "flags.h"
@@ -54,6 +61,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "omp-low.h"
 #include "gimple-low.h"
 #include "tree-cfgcleanup.h"
+#include "tree-nested.h"
 
 
 /* Lowering of OpenMP parallel and workshare constructs proceeds in two
@@ -281,7 +289,7 @@ extract_omp_for_data (gimple for_stmt, struct omp_for_data *fd,
   int i;
   struct omp_for_data_loop dummy_loop;
   location_t loc = gimple_location (for_stmt);
-  bool simd = gimple_omp_for_kind (for_stmt) == GF_OMP_FOR_KIND_SIMD;
+  bool simd = gimple_omp_for_kind (for_stmt) & GF_OMP_FOR_KIND_SIMD;
   bool distribute = gimple_omp_for_kind (for_stmt)
                    == GF_OMP_FOR_KIND_DISTRIBUTE;
 
@@ -373,6 +381,10 @@ extract_omp_for_data (gimple for_stmt, struct omp_for_data *fd,
        case LT_EXPR:
        case GT_EXPR:
          break;
+       case NE_EXPR:
+         gcc_assert (gimple_omp_for_kind (for_stmt)
+                     == GF_OMP_FOR_KIND_CILKSIMD);
+         break;
        case LE_EXPR:
          if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
            loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, 1);
@@ -999,7 +1011,7 @@ build_outer_var_ref (tree var, omp_context *ctx)
       x = build_receiver_ref (var, by_ref, ctx);
     }
   else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
-          && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD)
+          && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_SIMD)
     {
       /* #pragma omp simd isn't a worksharing construct, and can reference even
         private vars in its linear etc. clauses.  */
@@ -2226,7 +2238,7 @@ check_omp_nesting_restrictions (gimple stmt, omp_context *ctx)
   if (ctx != NULL)
     {
       if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
-         && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD)
+         && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_SIMD)
        {
          error_at (gimple_location (stmt),
                    "OpenMP constructs may not be nested inside simd region");
@@ -2249,7 +2261,7 @@ check_omp_nesting_restrictions (gimple stmt, omp_context *ctx)
   switch (gimple_code (stmt))
     {
     case GIMPLE_OMP_FOR:
-      if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_SIMD)
+      if (gimple_omp_for_kind (stmt) & GF_OMP_FOR_KIND_SIMD)
        return true;
       if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
        {
@@ -2281,8 +2293,8 @@ check_omp_nesting_restrictions (gimple stmt, omp_context *ctx)
                        : "#pragma omp cancellation point");
              return false;
            }
-         switch (host_integerp (gimple_call_arg (stmt, 0), 0)
-                 ? tree_low_cst (gimple_call_arg (stmt, 0), 0)
+         switch (tree_fits_shwi_p (gimple_call_arg (stmt, 0))
+                 ? tree_to_shwi (gimple_call_arg (stmt, 0))
                  : 0)
            {
            case 1:
@@ -2518,9 +2530,7 @@ scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
              if (tem != TREE_TYPE (t))
                {
                  if (TREE_CODE (t) == INTEGER_CST)
-                   *tp = build_int_cst_wide (tem,
-                                             TREE_INT_CST_LOW (t),
-                                             TREE_INT_CST_HIGH (t));
+                   *tp = wide_int_to_tree (tem, t);
                  else
                    TREE_TYPE (t) = tem;
                }
@@ -2532,6 +2542,23 @@ scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
   return NULL_TREE;
 }
 
+/* Return true if FNDECL is a setjmp or a longjmp.  */
+
+static bool
+setjmp_or_longjmp_p (const_tree fndecl)
+{
+  if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
+      && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SETJMP
+         || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LONGJMP))
+    return true;
+
+  tree declname = DECL_NAME (fndecl);
+  if (!declname)
+    return false;
+  const char *name = IDENTIFIER_POINTER (declname);
+  return !strcmp (name, "setjmp") || !strcmp (name, "longjmp");
+}
+
 
 /* Helper function for scan_omp.
 
@@ -2555,22 +2582,33 @@ scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
   else if (is_gimple_call (stmt))
     {
       tree fndecl = gimple_call_fndecl (stmt);
-      if (fndecl
-         && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
-       switch (DECL_FUNCTION_CODE (fndecl))
-         {
-         case BUILT_IN_GOMP_BARRIER:
-         case BUILT_IN_GOMP_CANCEL:
-         case BUILT_IN_GOMP_CANCELLATION_POINT:
-         case BUILT_IN_GOMP_TASKYIELD:
-         case BUILT_IN_GOMP_TASKWAIT:
-         case BUILT_IN_GOMP_TASKGROUP_START:
-         case BUILT_IN_GOMP_TASKGROUP_END:
-           remove = !check_omp_nesting_restrictions (stmt, ctx);
-           break;
-         default:
-           break;
-         }
+      if (fndecl)
+       {
+         if (setjmp_or_longjmp_p (fndecl)
+             && ctx
+             && gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
+             && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_SIMD)
+           {
+             remove = true;
+             error_at (gimple_location (stmt),
+                       "setjmp/longjmp inside simd construct");
+           }
+         else if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
+           switch (DECL_FUNCTION_CODE (fndecl))
+             {
+             case BUILT_IN_GOMP_BARRIER:
+             case BUILT_IN_GOMP_CANCEL:
+             case BUILT_IN_GOMP_CANCELLATION_POINT:
+             case BUILT_IN_GOMP_TASKYIELD:
+             case BUILT_IN_GOMP_TASKWAIT:
+             case BUILT_IN_GOMP_TASKGROUP_START:
+             case BUILT_IN_GOMP_TASKGROUP_END:
+               remove = !check_omp_nesting_restrictions (stmt, ctx);
+               break;
+             default:
+               break;
+             }
+       }
     }
   if (remove)
     {
@@ -2917,7 +2955,7 @@ lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf,
                                    OMP_CLAUSE_SAFELEN);
          if (c
              && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c), max_vf) == -1)
-           max_vf = tree_low_cst (OMP_CLAUSE_SAFELEN_EXPR (c), 0);
+           max_vf = tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c));
        }
       if (max_vf > 1)
        {
@@ -2963,7 +3001,7 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
   bool reduction_omp_orig_ref = false;
   int pass;
   bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
-                 && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD);
+                 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_SIMD);
   int max_vf = 0;
   tree lane = NULL_TREE, idx = NULL_TREE;
   tree ivar = NULL_TREE, lvar = NULL_TREE;
@@ -3583,7 +3621,7 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
       /* Don't add any barrier for #pragma omp simd or
         #pragma omp distribute.  */
       if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
-         || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR)
+         || gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_FOR)
        gimple_seq_add_stmt (ilist, build_omp_barrier (NULL_TREE));
     }
 
@@ -3662,7 +3700,7 @@ lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
     }
 
   if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
-      && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD)
+      && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_SIMD)
     {
       simduid = find_omp_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
       if (simduid)
@@ -3757,7 +3795,7 @@ lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
 
   /* SIMD reductions are handled in lower_rec_input_clauses.  */
   if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
-      && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD)
+      && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_SIMD)
     return;
 
   /* First see if there is exactly one reduction clause.  Use OMP_ATOMIC
@@ -6732,12 +6770,11 @@ expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
       else
        {
          safelen = OMP_CLAUSE_SAFELEN_EXPR (safelen);
-         if (!host_integerp (safelen, 1)
-             || (unsigned HOST_WIDE_INT) tree_low_cst (safelen, 1)
-                > INT_MAX)
+         if (!tree_fits_uhwi_p (safelen)
+             || tree_to_uhwi (safelen) > INT_MAX)
            loop->safelen = INT_MAX;
          else
-           loop->safelen = tree_low_cst (safelen, 1);
+           loop->safelen = tree_to_uhwi (safelen);
          if (loop->safelen == 1)
            loop->safelen = 0;
        }
@@ -6790,7 +6827,7 @@ expand_omp_for (struct omp_region *region, gimple inner_stmt)
        original loops from being detected.  Fix that up.  */
     loops_state_set (LOOPS_NEED_FIXUP);
 
-  if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_SIMD)
+  if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_KIND_SIMD)
     expand_omp_simd (region, &fd);
   else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
           && !fd.have_ordered)
@@ -7641,7 +7678,7 @@ expand_omp_atomic (struct omp_region *region)
   HOST_WIDE_INT index;
 
   /* Make sure the type is one of the supported sizes.  */
-  index = tree_low_cst (TYPE_SIZE_UNIT (type), 1);
+  index = tree_to_uhwi (TYPE_SIZE_UNIT (type));
   index = exact_log2 (index);
   if (index >= 0 && index <= 4)
     {
@@ -8196,7 +8233,7 @@ build_omp_regions (void)
 {
   gcc_assert (root_omp_region == NULL);
   calculate_dominance_info (CDI_DOMINATORS);
-  build_omp_regions_1 (ENTRY_BLOCK_PTR, NULL, false);
+  build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, false);
 }
 
 /* Main entry point for expanding OMP-GIMPLE into runtime calls.  */
@@ -8232,7 +8269,8 @@ execute_expand_omp (void)
 static bool
 gate_expand_omp (void)
 {
-  return ((flag_openmp != 0 || flag_openmp_simd != 0) && !seen_error ());
+  return ((flag_openmp != 0 || flag_openmp_simd != 0
+          || flag_enable_cilkplus != 0) && !seen_error ());
 }
 
 namespace {
@@ -8794,9 +8832,9 @@ lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
 
   /* When possible, use a strict equality expression.  This can let VRP
      type optimizations deduce the value and remove a copy.  */
-  if (host_integerp (fd->loop.step, 0))
+  if (tree_fits_shwi_p (fd->loop.step))
     {
-      HOST_WIDE_INT step = TREE_INT_CST_LOW (fd->loop.step);
+      HOST_WIDE_INT step = tree_to_shwi (fd->loop.step);
       if (step == 1 || step == -1)
        cond_code = EQ_EXPR;
     }
@@ -8814,7 +8852,7 @@ lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
       /* Optimize: v = 0; is usually cheaper than v = some_other_constant.  */
       vinit = fd->loop.n1;
       if (cond_code == EQ_EXPR
-         && host_integerp (fd->loop.n2, 0)
+         && tree_fits_shwi_p (fd->loop.n2)
          && ! integer_zerop (fd->loop.n2))
        vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
       else
@@ -10053,7 +10091,7 @@ execute_lower_omp (void)
 
   /* This pass always runs, to provide PROP_gimple_lomp.
      But there is nothing to do unless -fopenmp is given.  */
-  if (flag_openmp == 0 && flag_openmp_simd == 0)
+  if (flag_openmp == 0 && flag_openmp_simd == 0 && flag_enable_cilkplus == 0)
     return 0;
 
   all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
@@ -10173,12 +10211,33 @@ diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
     error ("invalid entry to OpenMP structured block");
 #endif
 
+  bool cilkplus_block = false;
+  if (flag_enable_cilkplus)
+    {
+      if ((branch_ctx
+          && gimple_code (branch_ctx) == GIMPLE_OMP_FOR
+          && gimple_omp_for_kind (branch_ctx) == GF_OMP_FOR_KIND_CILKSIMD)
+         || (gimple_code (label_ctx) == GIMPLE_OMP_FOR
+             && gimple_omp_for_kind (label_ctx) == GF_OMP_FOR_KIND_CILKSIMD))
+       cilkplus_block = true;
+    }
+
   /* If it's obvious we have an invalid entry, be specific about the error.  */
   if (branch_ctx == NULL)
-    error ("invalid entry to OpenMP structured block");
+    {
+      if (cilkplus_block)
+       error ("invalid entry to Cilk Plus structured block");
+      else
+       error ("invalid entry to OpenMP structured block");
+    }
   else
-    /* Otherwise, be vague and lazy, but efficient.  */
-    error ("invalid branch to/from an OpenMP structured block");
+    {
+      /* Otherwise, be vague and lazy, but efficient.  */
+      if (cilkplus_block)
+       error ("invalid branch to/from a Cilk Plus structured block");
+      else
+       error ("invalid branch to/from an OpenMP structured block");
+    }
 
   gsi_replace (gsi_p, gimple_build_nop (), false);
   return true;
@@ -10482,7 +10541,7 @@ diagnose_omp_structured_block_errors (void)
 static bool
 gate_diagnose_omp_blocks (void)
 {
-  return flag_openmp != 0;
+  return flag_openmp || flag_enable_cilkplus;
 }
 
 namespace {