Previous: Cleanups, Up: Statements

#### 10.7.7 OpenMP

All the statements starting with `OMP_` represent directives and clauses used by the OpenMP API http://www.openmp.org/.

`OMP_PARALLEL`
  Represents `#pragma omp parallel [clause1 ... clauseN]`. It has four operands:

  Operand `OMP_PARALLEL_BODY` is valid while in GENERIC and High GIMPLE forms. It contains the body of code to be executed by all the threads. During GIMPLE lowering, this operand becomes `NULL` and the body is emitted linearly after `OMP_PARALLEL`.

  Operand `OMP_PARALLEL_CLAUSES` is the list of clauses associated with the directive.

  Operand `OMP_PARALLEL_FN` is created by `pass_lower_omp`, it contains the `FUNCTION_DECL` for the function that will contain the body of the parallel region.

  Operand `OMP_PARALLEL_DATA_ARG` is also created by `pass_lower_omp`. If there are shared variables to be communicated to the children threads, this operand will contain the `VAR_DECL` that contains all the shared values and variables.

`OMP_FOR`
  Represents `#pragma omp for [clause1 ... clauseN]`. It has 5 operands:

  Operand `OMP_FOR_BODY` contains the loop body.

  Operand `OMP_FOR_CLAUSES` is the list of clauses associated with the directive.

  Operand `OMP_FOR_INIT` is the loop initialization code of the form `VAR = N1`.

  Operand `OMP_FOR_COND` is the loop conditional expression of the form `VAR {<,>,<=,>=} N2`.

  Operand `OMP_FOR_INCR` is the loop index increment of the form `VAR {+=,-=} INCR`.

  Operand `OMP_FOR_PRE_BODY` contains side-effect code from operands `OMP_FOR_INIT`, `OMP_FOR_COND` and `OMP_FOR_INC`. These side-effects are part of the `OMP_FOR` block but must be evaluated before the start of loop body.

  The loop index variable `VAR` must be a signed integer variable, which is implicitly private to each thread. Bounds `N1` and `N2` and the increment expression `INCR` are required to be loop invariant integer expressions that are evaluated without any synchronization. The evaluation order, frequency of evaluation and side-effects are unspecified by the standard.

`OMP_SECTIONS`
  Represents `#pragma omp sections [clause1 ... clauseN]`.

  Operand `OMP_SECTIONS_BODY` contains the sections body, which in turn contains a set of `OMP_SECTION` nodes for each of the concurrent sections delimited by `#pragma omp section`.

  Operand `OMP_SECTIONS_CLAUSES` is the list of clauses associated with the directive.

`OMP_SECTION`
  Section delimiter for `OMP_SECTIONS`.
`OMP_SINGLE`
  Represents `#pragma omp single`.

  Operand `OMP_SINGLE_BODY` contains the body of code to be executed by a single thread.

  Operand `OMP_SINGLE_CLAUSES` is the list of clauses associated with the directive.

`OMP_MASTER`
  Represents `#pragma omp master`.

  Operand `OMP_MASTER_BODY` contains the body of code to be executed by the master thread.

`OMP_ORDERED`
  Represents `#pragma omp ordered`.

  Operand `OMP_ORDERED_BODY` contains the body of code to be executed in the sequential order dictated by the loop index variable.

`OMP_CRITICAL`
  Represents `#pragma omp critical [name]`.

  Operand `OMP_CRITICAL_BODY` is the critical section.

  Operand `OMP_CRITICAL_NAME` is an optional identifier to label the critical section.

`OMP_RETURN`
  This does not represent any OpenMP directive, it is an artificial marker to indicate the end of the body of an OpenMP. It is used by the flow graph (`tree-cfg.c`) and OpenMP region building code (`omp-low.c`).
`OMP_CONTINUE`
  Similarly, this instruction does not represent an OpenMP directive, it is used by `OMP_FOR` and `OMP_SECTIONS` to mark the place where the code needs to loop to the next iteration (in the case of `OMP_FOR`) or the next section (in the case of `OMP_SECTIONS`).

  In some cases, `OMP_CONTINUE` is placed right before `OMP_RETURN`. But if there are cleanups that need to occur right after the looping body, it will be emitted between `OMP_CONTINUE` and `OMP_RETURN`.

`OMP_ATOMIC`
  Represents `#pragma omp atomic`.

  Operand 0 is the address at which the atomic operation is to be performed.

  Operand 1 is the expression to evaluate. The gimplifier tries three alternative code generation strategies. Whenever possible, an atomic update built-in is used. If that fails, a compare-and-swap loop is attempted. If that also fails, a regular critical section around the expression is used.

`OMP_CLAUSE`
  Represents clauses associated with one of the `OMP_` directives. Clauses are represented by separate subcodes defined in `tree.h`. Clauses codes can be one of: `OMP_CLAUSE_PRIVATE`, `OMP_CLAUSE_SHARED`, `OMP_CLAUSE_FIRSTPRIVATE`, `OMP_CLAUSE_LASTPRIVATE`, `OMP_CLAUSE_COPYIN`, `OMP_CLAUSE_COPYPRIVATE`, `OMP_CLAUSE_IF`, `OMP_CLAUSE_NUM_THREADS`, `OMP_CLAUSE_SCHEDULE`, `OMP_CLAUSE_NOWAIT`, `OMP_CLAUSE_ORDERED`, `OMP_CLAUSE_DEFAULT`, `OMP_CLAUSE_REDUCTION`, `OMP_CLAUSE_COLLAPSE`, `OMP_CLAUSE_UNTIED`, `OMP_CLAUSE_FINAL`, and `OMP_CLAUSE_MERGEABLE`. Each code represents the corresponding OpenMP clause.

  Clauses associated with the same directive are chained together via `OMP_CLAUSE_CHAIN`. Those clauses that accept a list of variables are restricted to exactly one, accessed with `OMP_CLAUSE_VAR`. Therefore, multiple variables under the same clause `C` need to be represented as multiple `C` clauses chained together. This facilitates adding new clauses during compilation.