case OMP_SCAN:
case OMP_SCOPE:
case OMP_SECTION:
+ case OMP_STRUCTURED_BLOCK:
case OMP_MASTER:
case OMP_MASKED:
case OMP_TASKGROUP:
break;
case OMP_MASTER:
+ case OMP_STRUCTURED_BLOCK:
omp_parallel_combined_clauses = NULL;
/* FALLTHRU */
case OMP_SECTION:
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}.
@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
* @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}::
@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}
gsi_next (gsi);
return;
+ case GIMPLE_OMP_STRUCTURED_BLOCK:
+ /* These are supposed to be removed already in OMP lowering. */
+ gcc_unreachable ();
+
case GIMPLE_NOP:
case GIMPLE_ASM:
case GIMPLE_ASSIGN:
}
}
-/* 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
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 ();
}
case GIMPLE_OMP_MASTER:
case GIMPLE_OMP_SECTION:
+ case GIMPLE_OMP_STRUCTURED_BLOCK:
dump_gimple_omp_block (buffer, gs, spc, flags);
break;
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:
}
+/* 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. */
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)
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);
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:
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: \
case OMP_SCOPE:
case OMP_SECTIONS:
case OMP_SECTION:
+ case OMP_STRUCTURED_BLOCK:
case OMP_SINGLE:
case OMP_MASTER:
case OMP_MASKED:
break;
case OMP_SECTION:
+ case OMP_STRUCTURED_BLOCK:
case OMP_MASTER:
case OMP_MASKED:
case OMP_ORDERED:
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;
&& code != OMP_SCAN
&& code != OMP_SECTIONS
&& code != OMP_SECTION
+ && code != OMP_STRUCTURED_BLOCK
&& code != OMP_SINGLE
&& code != OMP_SCOPE);
}
parent GIMPLE_OMP_SECTIONS region. */
break;
+ case GIMPLE_OMP_STRUCTURED_BLOCK:
+ /* We should have gotten rid of these in gimple lowering. */
+ gcc_unreachable ();
+
case GIMPLE_OMP_SINGLE:
case GIMPLE_OMP_SCOPE:
expand_omp_single (region);
}
/* FALLTHRU */
case GIMPLE_OMP_SECTION:
+ case GIMPLE_OMP_STRUCTURED_BLOCK:
case GIMPLE_OMP_MASTER:
case GIMPLE_OMP_ORDERED:
case GIMPLE_OMP_CRITICAL:
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);
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:
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:
(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
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:
break;
case GIMPLE_OMP_SECTION:
+ case GIMPLE_OMP_STRUCTURED_BLOCK:
case GIMPLE_OMP_MASTER:
case GIMPLE_OMP_MASKED:
case GIMPLE_OMP_ORDERED:
break;
case GIMPLE_OMP_SECTION:
+ case GIMPLE_OMP_STRUCTURED_BLOCK:
case GIMPLE_OMP_MASTER:
case GIMPLE_OMP_MASKED:
case GIMPLE_OMP_ORDERED:
/* 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:
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))
{
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)
#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)