@@ -8055,6 +8055,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
case OMP_SCAN:
case OMP_SCOPE:
case OMP_SECTION:
+ case OMP_STRUCTURED_BLOCK:
case OMP_MASTER:
case OMP_MASKED:
case OMP_TASKGROUP:
@@ -19692,6 +19692,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
break;
case OMP_MASTER:
+ case OMP_STRUCTURED_BLOCK:
omp_parallel_combined_clauses = NULL;
/* FALLTHRU */
case OMP_SECTION:
@@ -2488,6 +2488,20 @@ In some cases, @code{OMP_CONTINUE} is placed right before
occur right after the looping body, it will be emitted between
@code{OMP_CONTINUE} and @code{OMP_RETURN}.
+@item OMP_STRUCTURED_BLOCK
+
+This is another statement that doesn't correspond to an OpenMP directive.
+It is used to mark sections of code in another directive that must
+be structured block sequences, in particular for sequences of intervening code
+in the body of an @code{OMP_FOR}. It is not necessary to use this when the
+entire body of a directive is required to be a structured block sequence,
+since that is implicit in the representation of the corresponding node.
+
+This tree node is used only to allow error checking transfers of control
+in/out of the structured block sequence after gimplification.
+It has a single operand (@code{OMP_STRUCTURED_BLOCK_BODY}) that is
+the code within the structured block sequence.
+
@item OMP_ATOMIC
Represents @code{#pragma omp atomic}.
@@ -468,6 +468,7 @@ The following table briefly describes the GIMPLE instruction set.
@item @code{GIMPLE_OMP_SECTIONS_SWITCH} @tab x @tab x
@item @code{GIMPLE_OMP_SINGLE} @tab x @tab x
@item @code{GIMPLE_PHI} @tab @tab x
+@item @code{GIMPLE_OMP_STRUCTURED_BLOCK} @tab x @tab
@item @code{GIMPLE_RESX} @tab @tab x
@item @code{GIMPLE_RETURN} @tab x @tab x
@item @code{GIMPLE_SWITCH} @tab x @tab x
@@ -1040,6 +1041,7 @@ Return a deep copy of statement @code{STMT}.
* @code{GIMPLE_OMP_SECTION}::
* @code{GIMPLE_OMP_SECTIONS}::
* @code{GIMPLE_OMP_SINGLE}::
+* @code{GIMPLE_OMP_STRUCTURED_BLOCK}::
* @code{GIMPLE_PHI}::
* @code{GIMPLE_RESX}::
* @code{GIMPLE_RETURN}::
@@ -2160,6 +2162,23 @@ Set @code{CLAUSES} to be the clauses associated with @code{OMP_SINGLE} @code{G}.
@end deftypefn
+@node @code{GIMPLE_OMP_STRUCTURED_BLOCK}
+@subsection @code{GIMPLE_OMP_STRUCTURED_BLOCK}
+@cindex @code{GIMPLE_OMP_STRUCTURED_BLOCK}
+
+Like the GENERIC equivalent @code{OMP_STRUCTURED_BLOCK}, this GIMPLE
+statement does not correspond directly to an OpenMP directive, and
+exists only to permit error checking of transfers of control
+in/out of structured block sequences (the @code{diagnose_omp_blocks} pass
+in @file{omp-low.cc}). All @code{GIMPLE_OMP_STRUCTURED_BLOCK}
+nodes are eliminated during OpenMP lowering.
+
+@deftypefn {GIMPLE function} gimple gimple_build_omp_structured_block (gimple_seq body)
+Build a @code{GIMPLE_OMP_STRUCTURED_BLOCK} statement.
+@code{BODY} is the sequence of statements in the structured block sequence.
+@end deftypefn
+
+
@node @code{GIMPLE_PHI}
@subsection @code{GIMPLE_PHI}
@cindex @code{GIMPLE_PHI}
@@ -717,6 +717,11 @@ lower_stmt (gimple_stmt_iterator *gsi, struct lower_data *data)
gsi_next (gsi);
return;
+ case GIMPLE_OMP_STRUCTURED_BLOCK:
+ /* These are supposed to be removed already in OMP lowering. */
+ gcc_unreachable ();
+ break;
+
case GIMPLE_NOP:
case GIMPLE_ASM:
case GIMPLE_ASSIGN:
@@ -1896,7 +1896,7 @@ dump_gimple_omp_sections (pretty_printer *buffer, const gomp_sections *gs,
}
}
-/* Dump a GIMPLE_OMP_{MASTER,ORDERED,SECTION} tuple on the
+/* Dump a GIMPLE_OMP_{MASTER,ORDERED,SECTION,STRUCTURED_BLOCK} tuple on the
pretty_printer BUFFER. */
static void
@@ -1916,6 +1916,9 @@ dump_gimple_omp_block (pretty_printer *buffer, const gimple *gs, int spc,
case GIMPLE_OMP_SECTION:
pp_string (buffer, "#pragma omp section");
break;
+ case GIMPLE_OMP_STRUCTURED_BLOCK:
+ pp_string (buffer, "#pragma omp __structured_block");
+ break;
default:
gcc_unreachable ();
}
@@ -2801,6 +2804,7 @@ pp_gimple_stmt_1 (pretty_printer *buffer, const gimple *gs, int spc,
case GIMPLE_OMP_MASTER:
case GIMPLE_OMP_SECTION:
+ case GIMPLE_OMP_STRUCTURED_BLOCK:
dump_gimple_omp_block (buffer, gs, spc, flags);
break;
@@ -693,6 +693,7 @@ walk_gimple_stmt (gimple_stmt_iterator *gsi, walk_stmt_fn callback_stmt,
case GIMPLE_OMP_ORDERED:
case GIMPLE_OMP_SCAN:
case GIMPLE_OMP_SECTION:
+ case GIMPLE_OMP_STRUCTURED_BLOCK:
case GIMPLE_OMP_PARALLEL:
case GIMPLE_OMP_TASK:
case GIMPLE_OMP_SCOPE:
@@ -1038,6 +1038,21 @@ gimple_build_omp_section (gimple_seq body)
}
+/* Build a GIMPLE_OMP_STRUCTURED_BLOCK statement.
+
+ BODY is the structured block sequence. */
+
+gimple *
+gimple_build_omp_structured_block (gimple_seq body)
+{
+ gimple *p = gimple_alloc (GIMPLE_OMP_STRUCTURED_BLOCK, 0);
+ if (body)
+ gimple_omp_set_body (p, body);
+
+ return p;
+}
+
+
/* Build a GIMPLE_OMP_MASTER statement.
BODY is the sequence of statements to be executed by just the master. */
@@ -275,6 +275,11 @@ DEFGSCODE(GIMPLE_OMP_CRITICAL, "gimple_omp_critical", GSS_OMP_CRITICAL)
unspecified by the standards. */
DEFGSCODE(GIMPLE_OMP_FOR, "gimple_omp_for", GSS_OMP_FOR)
+/* GIMPLE_STRUCTURED_BLOCK <BODY> is an internal construct used to assert
+ that BODY is a structured block sequence, with no other semantics. It is
+ used to allow error-checking of intervening code in OMP_FOR constructs. */
+DEFGSCODE(GIMPLE_OMP_STRUCTURED_BLOCK, "gimple_omp_structured_block", GSS_OMP)
+
/* GIMPLE_OMP_MASTER <BODY> represents #pragma omp master.
BODY is the sequence of statements to execute in the master section. */
DEFGSCODE(GIMPLE_OMP_MASTER, "gimple_omp_master", GSS_OMP)
@@ -1591,6 +1591,7 @@ gomp_parallel *gimple_build_omp_parallel (gimple_seq, tree, tree, tree);
gomp_task *gimple_build_omp_task (gimple_seq, tree, tree, tree, tree,
tree, tree);
gimple *gimple_build_omp_section (gimple_seq);
+gimple *gimple_build_omp_structured_block (gimple_seq);
gimple *gimple_build_omp_scope (gimple_seq, tree);
gimple *gimple_build_omp_master (gimple_seq);
gimple *gimple_build_omp_masked (gimple_seq, tree);
@@ -1879,6 +1880,7 @@ gimple_has_substatements (gimple *g)
case GIMPLE_OMP_TASKGROUP:
case GIMPLE_OMP_ORDERED:
case GIMPLE_OMP_SECTION:
+ case GIMPLE_OMP_STRUCTURED_BLOCK:
case GIMPLE_OMP_PARALLEL:
case GIMPLE_OMP_TASK:
case GIMPLE_OMP_SCOPE:
@@ -6723,6 +6725,7 @@ gimple_return_set_retval (greturn *gs, tree retval)
case GIMPLE_OMP_TEAMS: \
case GIMPLE_OMP_SCOPE: \
case GIMPLE_OMP_SECTION: \
+ case GIMPLE_OMP_STRUCTURED_BLOCK: \
case GIMPLE_OMP_MASTER: \
case GIMPLE_OMP_MASKED: \
case GIMPLE_OMP_TASKGROUP: \
@@ -5977,6 +5977,7 @@ is_gimple_stmt (tree t)
case OMP_SCOPE:
case OMP_SECTIONS:
case OMP_SECTION:
+ case OMP_STRUCTURED_BLOCK:
case OMP_SINGLE:
case OMP_MASTER:
case OMP_MASKED:
@@ -16995,6 +16996,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
break;
case OMP_SECTION:
+ case OMP_STRUCTURED_BLOCK:
case OMP_MASTER:
case OMP_MASKED:
case OMP_ORDERED:
@@ -17013,6 +17015,9 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
case OMP_SECTION:
g = gimple_build_omp_section (body);
break;
+ case OMP_STRUCTURED_BLOCK:
+ g = gimple_build_omp_structured_block (body);
+ break;
case OMP_MASTER:
g = gimple_build_omp_master (body);
break;
@@ -17413,6 +17418,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
&& code != OMP_SCAN
&& code != OMP_SECTIONS
&& code != OMP_SECTION
+ && code != OMP_STRUCTURED_BLOCK
&& code != OMP_SINGLE
&& code != OMP_SCOPE);
}
@@ -10592,6 +10592,11 @@ expand_omp (struct omp_region *region)
parent GIMPLE_OMP_SECTIONS region. */
break;
+ case GIMPLE_OMP_STRUCTURED_BLOCK:
+ /* We should have gotten rid of these in gimple lowering. */
+ gcc_unreachable ();
+ break;
+
case GIMPLE_OMP_SINGLE:
case GIMPLE_OMP_SCOPE:
expand_omp_single (region);
@@ -4300,6 +4300,7 @@ scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
}
/* FALLTHRU */
case GIMPLE_OMP_SECTION:
+ case GIMPLE_OMP_STRUCTURED_BLOCK:
case GIMPLE_OMP_MASTER:
case GIMPLE_OMP_ORDERED:
case GIMPLE_OMP_CRITICAL:
@@ -14499,6 +14500,14 @@ lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
gcc_assert (ctx);
lower_omp_single (gsi_p, ctx);
break;
+ case GIMPLE_OMP_STRUCTURED_BLOCK:
+ /* We have already done error checking at this point, so these nodes
+ can be completely removed and replaced with their body. */
+ ctx = maybe_lookup_ctx (stmt);
+ gcc_assert (ctx);
+ lower_omp (gimple_omp_body_ptr (stmt), ctx);
+ gsi_replace_with_seq (gsi_p, gimple_omp_body (stmt), true);
+ break;
case GIMPLE_OMP_MASTER:
case GIMPLE_OMP_MASKED:
ctx = maybe_lookup_ctx (stmt);
@@ -14886,6 +14895,7 @@ diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
case GIMPLE_OMP_SECTIONS:
case GIMPLE_OMP_SINGLE:
case GIMPLE_OMP_SECTION:
+ case GIMPLE_OMP_STRUCTURED_BLOCK:
case GIMPLE_OMP_MASTER:
case GIMPLE_OMP_MASKED:
case GIMPLE_OMP_ORDERED:
@@ -14949,6 +14959,7 @@ diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
case GIMPLE_OMP_SECTIONS:
case GIMPLE_OMP_SINGLE:
case GIMPLE_OMP_SECTION:
+ case GIMPLE_OMP_STRUCTURED_BLOCK:
case GIMPLE_OMP_MASTER:
case GIMPLE_OMP_MASKED:
case GIMPLE_OMP_ORDERED:
@@ -1708,6 +1708,11 @@ remap_gimple_stmt (gimple *stmt, copy_body_data *id)
(s1, gimple_omp_sections_clauses (stmt));
break;
+ case GIMPLE_OMP_STRUCTURED_BLOCK:
+ s1 = remap_gimple_seq (gimple_omp_body (stmt), id);
+ copy = gimple_build_omp_structured_block (s1);
+ break;
+
case GIMPLE_OMP_SINGLE:
s1 = remap_gimple_seq (gimple_omp_body (stmt), id);
copy = gimple_build_omp_single
@@ -4561,6 +4566,7 @@ estimate_num_insns (gimple *stmt, eni_weights *weights)
case GIMPLE_OMP_SCAN:
case GIMPLE_OMP_SECTION:
case GIMPLE_OMP_SECTIONS:
+ case GIMPLE_OMP_STRUCTURED_BLOCK:
case GIMPLE_OMP_SINGLE:
case GIMPLE_OMP_TARGET:
case GIMPLE_OMP_TEAMS:
@@ -1795,6 +1795,7 @@ convert_nonlocal_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
break;
case GIMPLE_OMP_SECTION:
+ case GIMPLE_OMP_STRUCTURED_BLOCK:
case GIMPLE_OMP_MASTER:
case GIMPLE_OMP_MASKED:
case GIMPLE_OMP_ORDERED:
@@ -2540,6 +2541,7 @@ convert_local_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
break;
case GIMPLE_OMP_SECTION:
+ case GIMPLE_OMP_STRUCTURED_BLOCK:
case GIMPLE_OMP_MASTER:
case GIMPLE_OMP_MASKED:
case GIMPLE_OMP_ORDERED:
@@ -3050,6 +3052,7 @@ convert_gimple_call (gimple_stmt_iterator *gsi, bool *handled_ops_p,
/* FALLTHRU */
case GIMPLE_OMP_SECTIONS:
case GIMPLE_OMP_SECTION:
+ case GIMPLE_OMP_STRUCTURED_BLOCK:
case GIMPLE_OMP_SINGLE:
case GIMPLE_OMP_SCOPE:
case GIMPLE_OMP_MASTER:
@@ -3741,6 +3741,10 @@ dump_generic_node (pretty_printer *pp, tree node, int spc, dump_flags_t flags,
pp_string (pp, "#pragma omp section");
goto dump_omp_body;
+ case OMP_STRUCTURED_BLOCK:
+ pp_string (pp, "#pragma omp __structured_block");
+ goto dump_omp_body;
+
case OMP_SCAN:
if (OMP_SCAN_CLAUSES (node))
{
@@ -1287,6 +1287,15 @@ DEFTREECODE (OMP_SCAN, "omp_scan", tcc_statement, 2)
Operand 0: OMP_SECTION_BODY: Section body. */
DEFTREECODE (OMP_SECTION, "omp_section", tcc_statement, 1)
+/* OpenMP structured block sequences that don't correspond to the body
+ another directive. This is used for code fragments within the body
+ of a directive that are separately required to be structured block
+ sequence; in particular, for intervening code sequences in
+ imperfectly-nested loops.
+ Operand 0: BODY: contains the statement(s) within the structured block
+ sequence. */
+DEFTREECODE (OMP_STRUCTURED_BLOCK, "omp_structured_block", tcc_statement, 1)
+
/* OpenMP - #pragma omp master
Operand 0: OMP_MASTER_BODY: Master section body. */
DEFTREECODE (OMP_MASTER, "omp_master", tcc_statement, 1)
@@ -1530,6 +1530,9 @@ class auto_suppress_location_wrappers
#define OMP_SECTION_BODY(NODE) TREE_OPERAND (OMP_SECTION_CHECK (NODE), 0)
+#define OMP_STRUCTURED_BLOCK_BODY(NODE) \
+ TREE_OPERAND (OMP_STRUCTURED_BLOCK_CHECK (NODE), 0)
+
#define OMP_SINGLE_BODY(NODE) TREE_OPERAND (OMP_SINGLE_CHECK (NODE), 0)
#define OMP_SINGLE_CLAUSES(NODE) TREE_OPERAND (OMP_SINGLE_CHECK (NODE), 1)