#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"
#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"
#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
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;
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);
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. */
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");
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)
{
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.
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)
{
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;
/* 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));
}
}
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)
/* 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
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)
{
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. */
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 {
/* 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,
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;
static bool
gate_diagnose_omp_blocks (void)
{
- return flag_openmp != 0;
+ return flag_openmp || flag_enable_cilkplus;
}
namespace {