GCC Middle and Back End API Reference
omp-expand.cc File Reference
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "memmodel.h"
#include "backend.h"
#include "target.h"
#include "rtl.h"
#include "tree.h"
#include "gimple.h"
#include "cfghooks.h"
#include "tree-pass.h"
#include "ssa.h"
#include "optabs.h"
#include "cgraph.h"
#include "pretty-print.h"
#include "diagnostic-core.h"
#include "fold-const.h"
#include "stor-layout.h"
#include "cfganal.h"
#include "internal-fn.h"
#include "gimplify.h"
#include "gimple-iterator.h"
#include "gimplify-me.h"
#include "gimple-walk.h"
#include "tree-cfg.h"
#include "tree-into-ssa.h"
#include "tree-ssa.h"
#include "splay-tree.h"
#include "cfgloop.h"
#include "omp-general.h"
#include "omp-offload.h"
#include "tree-cfgcleanup.h"
#include "alloc-pool.h"
#include "symbol-summary.h"
#include "gomp-constants.h"
#include "gimple-pretty-print.h"
#include "stringpool.h"
#include "attribs.h"
#include "tree-eh.h"
#include "opts.h"
Include dependency graph for omp-expand.cc:

Data Structures

struct  omp_region
 
struct  oacc_collapse
 

Functions

static void expand_omp_build_assign (gimple_stmt_iterator *, tree, tree, bool=false)
 
static gphifind_phi_with_arg_on_edge (tree, edge)
 
static void expand_omp (struct omp_region *region)
 
static bool is_combined_parallel (struct omp_region *region)
 
static bool workshare_safe_to_combine_p (basic_block ws_entry_bb)
 
static tree omp_adjust_chunk_size (tree chunk_size, bool simd_schedule)
 
static vec< tree, va_gc > * get_ws_args_for (gimple *par_stmt, gimple *ws_stmt)
 
static void determine_parallel_type (struct omp_region *region)
 
void dump_omp_region (FILE *, struct omp_region *, int)
 
void debug_omp_region (struct omp_region *)
 
void debug_all_omp_regions (void)
 
static struct omp_regionnew_omp_region (basic_block bb, enum gimple_code type, struct omp_region *parent)
 
static void free_omp_region_1 (struct omp_region *region)
 
void omp_free_regions (void)
 
static gcondgimple_build_cond_empty (tree cond)
 
static void adjust_context_and_scope (struct omp_region *region, tree entry_block, tree child_fndecl)
 
static void expand_parallel_call (struct omp_region *region, basic_block bb, gomp_parallel *entry_stmt, vec< tree, va_gc > *ws_args)
 
static void expand_task_call (struct omp_region *region, basic_block bb, gomp_task *entry_stmt)
 
static void expand_taskwait_call (basic_block bb, gomp_task *entry_stmt)
 
static void expand_teams_call (basic_block bb, gomp_teams *entry_stmt)
 
static tree vec2chain (vec< tree, va_gc > *v)
 
static void remove_exit_barrier (struct omp_region *region)
 
static void remove_exit_barriers (struct omp_region *region)
 
static void optimize_omp_library_calls (gimple *entry_stmt)
 
static tree expand_omp_regimplify_p (tree *tp, int *walk_subtrees, void *)
 
static gcondexpand_omp_build_cond (gimple_stmt_iterator *gsi_p, enum tree_code code, tree lhs, tree rhs, bool after=false)
 
static void expand_omp_taskreg (struct omp_region *region)
 
static tree expand_oacc_collapse_init (const struct omp_for_data *fd, gimple_stmt_iterator *gsi, oacc_collapse *counts, tree diff_type, tree bound_type, location_t loc)
 
static void expand_oacc_collapse_vars (const struct omp_for_data *fd, bool inner, gimple_stmt_iterator *gsi, const oacc_collapse *counts, tree ivar, tree diff_type)
 
static void expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi, basic_block &entry_bb, tree *counts, basic_block &zero_iter1_bb, int &first_zero_iter1, basic_block &zero_iter2_bb, int &first_zero_iter2, basic_block &l2_dom_bb)
 
static void expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi, tree *counts, tree *nonrect_bounds, gimple *inner_stmt, tree startvar)
 
static basic_block extract_omp_for_update_vars (struct omp_for_data *fd, tree *nonrect_bounds, basic_block cont_bb, basic_block body_bb)
 
static void expand_omp_ordered_source (gimple_stmt_iterator *gsi, struct omp_for_data *fd, tree *counts, location_t loc)
 
static void expand_omp_ordered_sink (gimple_stmt_iterator *gsi, struct omp_for_data *fd, tree *counts, tree c, location_t loc, basic_block cont_bb)
 
static void expand_omp_ordered_source_sink (struct omp_region *region, struct omp_for_data *fd, tree *counts, basic_block cont_bb)
 
static basic_block expand_omp_for_ordered_loops (struct omp_for_data *fd, tree *counts, basic_block cont_bb, basic_block body_bb, basic_block l0_bb, bool ordered_lastprivate)
 
static void expand_omp_for_generic (struct omp_region *region, struct omp_for_data *fd, enum built_in_function start_fn, enum built_in_function next_fn, tree sched_arg, gimple *inner_stmt)
 
static tree expand_omp_scantemp_alloc (tree clauses, tree ptr, unsigned HOST_WIDE_INT sz, unsigned HOST_WIDE_INT alloc_align, tree cnt, gimple_stmt_iterator *gsi, bool alloc)
 
static tree find_lastprivate_looptemp (struct omp_for_data *fd, tree innerc)
 
static void expand_omp_for_static_nochunk (struct omp_region *region, struct omp_for_data *fd, gimple *inner_stmt)
 
static void expand_omp_for_static_chunk (struct omp_region *region, struct omp_for_data *fd, gimple *inner_stmt)
 
static void expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
 
static void expand_omp_taskloop_for_outer (struct omp_region *region, struct omp_for_data *fd, gimple *inner_stmt)
 
static void expand_omp_taskloop_for_inner (struct omp_region *region, struct omp_for_data *fd, gimple *inner_stmt)
 
static void expand_oacc_for (struct omp_region *region, struct omp_for_data *fd)
 
static void expand_omp_for (struct omp_region *region, gimple *inner_stmt)
 
static void expand_omp_sections (struct omp_region *region)
 
static void expand_omp_single (struct omp_region *region)
 
static void expand_omp_synch (struct omp_region *region)
 
static enum memmodel omp_memory_order_to_fail_memmodel (enum omp_memory_order mo)
 
static enum memmodel omp_memory_order_to_memmodel (enum omp_memory_order mo)
 
static bool expand_omp_atomic_load (basic_block load_bb, tree addr, tree loaded_val, int index)
 
static bool expand_omp_atomic_store (basic_block load_bb, tree addr, tree loaded_val, tree stored_val, int index)
 
static bool expand_omp_atomic_fetch_op (basic_block load_bb, tree addr, tree loaded_val, tree stored_val, int index)
 
static bool expand_omp_atomic_cas (basic_block load_bb, tree addr, tree loaded_val, tree stored_val, int index)
 
static bool expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb, tree addr, tree loaded_val, tree stored_val, int index)
 
static bool expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb, tree addr, tree loaded_val, tree stored_val)
 
static void expand_omp_atomic (struct omp_region *region)
 
static void mark_loops_in_oacc_kernels_region (basic_block region_entry, basic_block region_exit)
 
static tree get_target_argument_identifier_1 (int device, bool subseqent_param, int id)
 
static tree get_target_argument_identifier (int device, bool subseqent_param, int id)
 
static tree get_target_argument_value (gimple_stmt_iterator *gsi, int device, int id, tree value)
 
static void push_target_argument_according_to_value (gimple_stmt_iterator *gsi, int device, int id, tree value, vec< tree > *args)
 
static tree get_target_arguments (gimple_stmt_iterator *gsi, gomp_target *tgt_stmt)
 
static void expand_omp_target (struct omp_region *region)
 
static void build_omp_regions_1 (basic_block bb, struct omp_region *parent, bool single_tree)
 
static void build_omp_regions_root (basic_block root)
 
void omp_expand_local (basic_block head)
 
static void build_omp_regions (void)
 
static unsigned int execute_expand_omp (void)
 
gimple_opt_passmake_pass_expand_omp (gcc::context *ctxt)
 
gimple_opt_passmake_pass_expand_omp_ssa (gcc::context *ctxt)
 
bool omp_make_gimple_edges (basic_block bb, struct omp_region **region, int *region_idx)
 

Variables

static struct omp_regionroot_omp_region
 
static bool omp_any_child_fn_dumped
 

Function Documentation

◆ adjust_context_and_scope()

static void adjust_context_and_scope ( struct omp_region * region,
tree entry_block,
tree child_fndecl )
static
Change DECL_CONTEXT of CHILD_FNDECL to that of the parent function.
Add CHILD_FNDECL to decl chain of the supercontext of the block
ENTRY_BLOCK - this is the block which originally contained the
code from which CHILD_FNDECL was created.

Together, these actions ensure that the debug info for the outlined
function will be emitted with the correct lexical scope.   

References b, BLOCK_SUPERCONTEXT, BLOCK_VARS, current_function_decl, DECL_CHAIN, DECL_CONTEXT, omp_region::entry, ggc_alloc(), gimple_omp_target_child_fn(), gimple_omp_taskreg_child_fn(), last_nondebug_stmt(), NULL_TREE, omp_region::outer, TREE_CODE, and omp_region::type.

Referenced by expand_omp_target(), and expand_omp_taskreg().

◆ build_omp_regions()

static void build_omp_regions ( void )
static
Scan the CFG and build a tree of OMP regions.  Return the root of
the OMP region tree.   

References build_omp_regions_1(), calculate_dominance_info(), CDI_DOMINATORS, cfun, ENTRY_BLOCK_PTR_FOR_FN, gcc_assert, NULL, and root_omp_region.

Referenced by execute_expand_omp().

◆ build_omp_regions_1()

◆ build_omp_regions_root()

static void build_omp_regions_root ( basic_block root)
static
Builds the tree of OMP regions rooted at ROOT, storing it to
root_omp_region.   

References build_omp_regions_1(), gcc_assert, NULL, and root_omp_region.

Referenced by omp_expand_local().

◆ debug_all_omp_regions()

DEBUG_FUNCTION void debug_all_omp_regions ( void )

◆ debug_omp_region()

DEBUG_FUNCTION void debug_omp_region ( struct omp_region * region)

References dump_omp_region(), and ggc_alloc().

◆ determine_parallel_type()

◆ dump_omp_region()

void dump_omp_region ( FILE * file,
struct omp_region * region,
int indent )

◆ execute_expand_omp()

static unsigned int execute_expand_omp ( void )
static

◆ expand_oacc_collapse_init()

static tree expand_oacc_collapse_init ( const struct omp_for_data * fd,
gimple_stmt_iterator * gsi,
oacc_collapse * counts,
tree diff_type,
tree bound_type,
location_t loc )
static

◆ expand_oacc_collapse_vars()

static void expand_oacc_collapse_vars ( const struct omp_for_data * fd,
bool inner,
gimple_stmt_iterator * gsi,
const oacc_collapse * counts,
tree ivar,
tree diff_type )
static
Emit initializers for collapsed loop members.  INNER is true if
this is for the element loop of a TILE.  IVAR is the outer
loop iteration variable, from which collapsed loop iteration values
are  calculated.  COUNTS array has been initialized by
expand_oacc_collapse_inits.   

References oacc_collapse::base, expr, fold_build2, fold_convert, force_gimple_operand_gsi(), ggc_alloc(), gimple_build_assign(), gsi_insert_before(), GSI_SAME_STMT, oacc_collapse::iters, NULL_TREE, oacc_collapse::outer, POINTER_TYPE_P, sizetype, oacc_collapse::step, and TREE_TYPE.

Referenced by expand_oacc_for().

◆ expand_oacc_for()

static void expand_oacc_for ( struct omp_region * region,
struct omp_for_data * fd )
static
A subroutine of expand_omp_for.  Generate code for an OpenACC
partitioned loop.  The lowering here is abstracted, in that the
loop parameters are passed through internal functions, which are
further lowered by oacc_device_lower, once we get to the target
compiler.  The loop is of the form:

for (V = B; V LTGT E; V += S) {BODY}

where LTGT is < or >.  We may have a specified chunking size, CHUNKING
(constant 0 for no chunking) and we will have a GWV partitioning
mask, specifying dimensions over which the loop is to be
partitioned (see note below).  We generate code that looks like
(this ignores tiling):

<entry_bb> [incoming FALL->body, BRANCH->exit]
  typedef signedintify (typeof (V)) T;  // underlying signed integral type
  T range = E - B;
  T chunk_no = 0;
  T DIR = LTGT == '<' ? +1 : -1;
  T chunk_max = GOACC_LOOP_CHUNK (dir, range, S, CHUNK_SIZE, GWV);
  T step = GOACC_LOOP_STEP (dir, range, S, CHUNK_SIZE, GWV);

<head_bb> [created by splitting end of entry_bb]
  T offset = GOACC_LOOP_OFFSET (dir, range, S, CHUNK_SIZE, GWV, chunk_no);
  T bound = GOACC_LOOP_BOUND (dir, range, S, CHUNK_SIZE, GWV, offset);
  if (!(offset LTGT bound)) goto bottom_bb;

<body_bb> [incoming]
  V = B + offset;
  {BODY}

<cont_bb> [incoming, may == body_bb FALL->exit_bb, BRANCH->body_bb]
  offset += step;
  if (offset LTGT bound) goto body_bb; [*]

<bottom_bb> [created by splitting start of exit_bb] insert BRANCH->head_bb
  chunk_no++;
  if (chunk < chunk_max) goto head_bb;

<exit_bb> [incoming]
  V = B + ((range -/+ 1) / S +/- 1) * S [*]

[*] Needed if V live at end of loop.   

References add_loop(), alloc_loop(), b, boolean_type_node, BRANCH_EDGE, build2(), build_int_cst(), cfun, omp_region::cont, create_tmp_var, current_function_decl, DECL_ATTRIBUTES, EDGE_COUNT, EDGE_SUCC, omp_region::entry, profile_probability::even(), omp_region::exit, expand_oacc_collapse_init(), expand_oacc_collapse_vars(), expr, FALLTHRU_EDGE, fold_build1, fold_build2, fold_convert, force_gimple_operand_gsi(), gcc_assert, gcc_checking_assert, GF_OMP_FOR_KIND_OACC_LOOP, ggc_alloc(), gimple_build_assign(), gimple_build_call_internal(), gimple_build_cond_empty(), gimple_build_nop(), gimple_call_set_lhs(), gimple_in_ssa_p(), gimple_location(), gimple_omp_continue_control_def(), gimple_omp_continue_control_use(), gimple_omp_for_combined_into_p(), gimple_omp_for_index(), gimple_omp_for_kind(), gimple_set_location(), GSI_CONTINUE_LINKING, gsi_for_stmt(), gsi_insert_after(), gsi_insert_before(), gsi_last_bb(), gsi_last_nondebug_bb(), gsi_remove(), GSI_SAME_STMT, gsi_start_bb(), gsi_stmt(), profile_probability::guessed(), loop::header, integer_minus_one_node, integer_type_node, integer_zero_node, integer_zerop(), is_oacc_kernels(), last_nondebug_stmt(), loop::latch, profile_probability::likely(), lookup_attribute(), basic_block_def::loop_father, make_edge(), NULL, NULL_TREE, offset, POINTER_TYPE_P, basic_block_def::preds, signed_type_for(), single_pred(), single_succ_edge(), sizetype, split_block(), SSA_VAR_P, oacc_collapse::step, basic_block_def::succs, oacc_collapse::tile, TREE_TYPE, TYPE_PRECISION, TYPE_UNSIGNED, and profile_probability::unlikely().

Referenced by expand_omp_for().

◆ expand_omp()

static void expand_omp ( struct omp_region * region)
static
Expand the parallel region tree rooted at REGION.  Expansion
proceeds in depth-first order.  Innermost regions are expanded
first.  This way, parallel regions that require a new function to
be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
internal dependencies in their body.   

References current_function_decl, determine_parallel_type(), dump_file, dump_flags, dump_function_header(), omp_region::entry, expand_omp(), expand_omp_atomic(), expand_omp_for(), expand_omp_sections(), expand_omp_single(), expand_omp_synch(), expand_omp_target(), expand_omp_taskreg(), gcc_assert, gcc_unreachable, ggc_alloc(), gimple_has_location(), gimple_location(), gimple_omp_for_combined_p(), gimple_omp_ordered_standalone_p(), omp_region::inner, input_location, last_nondebug_stmt(), omp_region::next, NULL, omp_any_child_fn_dumped, omp_region::ord_stmt, omp_region::outer, and omp_region::type.

Referenced by execute_expand_omp(), expand_omp(), and omp_expand_local().

◆ expand_omp_atomic()

static void expand_omp_atomic ( struct omp_region * region)
static
Expand an GIMPLE_OMP_ATOMIC statement.  We try to expand
using expand_omp_atomic_fetch_op.  If it failed, we try to
call expand_omp_atomic_pipeline, and if it fails too, the
ultimate fallback is wrapping the operation in a mutex
(expand_omp_atomic_mutex).  REGION is the atomic region built
by build_omp_regions_1().   

References BITS_PER_WORD, cfun, omp_region::entry, exact_log2(), omp_region::exit, expand_omp_atomic_cas(), expand_omp_atomic_fetch_op(), expand_omp_atomic_load(), expand_omp_atomic_mutex(), expand_omp_atomic_pipeline(), expand_omp_atomic_store(), first_stmt(), GET_MODE_BITSIZE(), ggc_alloc(), gimple_in_ssa_p(), gimple_omp_atomic_load_lhs(), gimple_omp_atomic_load_rhs(), gimple_omp_atomic_store_val(), INTEGRAL_TYPE_P, is_float_mode(), is_int_mode(), last_nondebug_stmt(), POINTER_TYPE_P, single_succ(), tree_to_uhwi(), TREE_TYPE, TYPE_ALIGN_UNIT, TYPE_MAIN_VARIANT, TYPE_MODE, and TYPE_SIZE_UNIT.

Referenced by expand_omp().

◆ expand_omp_atomic_cas()

◆ expand_omp_atomic_fetch_op()

◆ expand_omp_atomic_load()

◆ expand_omp_atomic_mutex()

static bool expand_omp_atomic_mutex ( basic_block load_bb,
basic_block store_bb,
tree addr,
tree loaded_val,
tree stored_val )
static
A subroutine of expand_omp_atomic.  Implement the atomic operation as:

                          GOMP_atomic_start ();
                          *addr = rhs;
                          GOMP_atomic_end ();

  The result is not globally atomic, but works so long as all parallel
  references are within #pragma omp atomic directives.  According to
  responses received from omp@openmp.org, appears to be within spec.
  Which makes sense, since that's how several other compilers handle
  this situation as well.
  LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
  expanding.  STORED_VAL is the operand of the matching
  GIMPLE_OMP_ATOMIC_STORE.

  We replace
  GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
  loaded_val = *addr;

  and replace
  GIMPLE_OMP_ATOMIC_STORE (stored_val)  with
  *addr = stored_val;

References build_call_expr(), build_pointer_type_for_mode(), build_simple_mem_ref, builtin_decl_explicit(), fold_convert, force_gimple_operand_gsi(), gcc_assert, ggc_alloc(), gimple_build_assign(), gimple_set_vdef(), gimple_set_vuse(), gimple_vdef(), gimple_vuse(), gsi_insert_before(), gsi_last_nondebug_bb(), gsi_remove(), GSI_SAME_STMT, gsi_stmt(), NULL_TREE, ptr_mode, si, TREE_OPERAND, TREE_TYPE, and unshare_expr().

Referenced by expand_omp_atomic().

◆ expand_omp_atomic_pipeline()

static bool expand_omp_atomic_pipeline ( basic_block load_bb,
basic_block store_bb,
tree addr,
tree loaded_val,
tree stored_val,
int index )
static
A subroutine of expand_omp_atomic.  Implement the atomic operation as:

   oldval = *addr;
   repeat:
     newval = rhs;       // with oldval replacing *addr in rhs
     oldval = __sync_val_compare_and_swap (addr, oldval, newval);
     if (oldval != newval)
       goto repeat;

INDEX is log2 of the size of the data type, and thus usable to find the
index of the builtin decl.   

References add_loop(), alloc_loop(), boolean_type_node, build1(), build2(), build_call_expr(), build_call_expr_internal_loc(), build_complex_type(), build_int_cst(), build_pointer_type_for_mode(), builtin_decl_explicit(), can_atomic_load_p(), can_compare_and_swap_p(), cfun, create_phi_node(), create_tmp_reg(), create_tmp_var, fold_convert, force_gimple_operand_gsi(), gcc_assert, ggc_alloc(), gimple_build_assign(), gimple_build_cond_empty(), gimple_in_ssa_p(), gimple_location(), gimple_omp_atomic_memory_order(), gimple_seq_empty_p(), gimple_seq_first_stmt(), gsi_insert_before(), gsi_last_nondebug_bb(), gsi_remove(), GSI_SAME_STMT, gsi_start_bb(), gsi_stmt(), profile_probability::guessed_always(), profile_probability::guessed_never(), loop::header, int_size_in_bytes(), integer_type_node, INTEGRAL_TYPE_P, loop::latch, make_edge(), make_ssa_name(), MEMMODEL_RELAXED, NULL, NULL_TREE, omp_memory_order_to_fail_memmodel(), omp_memory_order_to_memmodel(), PHI_ARG_DEF_PTR_FROM_EDGE, phi_nodes(), POINTER_TYPE_P, ptr_mode, release_defs(), SET_USE, si, single_succ(), single_succ_edge(), TREE_TYPE, type(), TYPE_MAIN_VARIANT, and TYPE_MODE.

Referenced by expand_omp_atomic().

◆ expand_omp_atomic_store()

◆ expand_omp_build_assign()

◆ expand_omp_build_cond()

◆ expand_omp_for()

◆ expand_omp_for_generic()

static void expand_omp_for_generic ( struct omp_region * region,
struct omp_for_data * fd,
enum built_in_function start_fn,
enum built_in_function next_fn,
tree sched_arg,
gimple * inner_stmt )
static
A subroutine of expand_omp_for.  Generate code for a parallel
loop with any schedule.  Given parameters:

     for (V = N1; V cond N2; V += STEP) BODY;

where COND is "<" or ">", we generate pseudocode

     more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
     if (more) goto L0; else goto L3;
 L0:
     V = istart0;
     iend = iend0;
 L1:
     BODY;
     V += STEP;
     if (V cond iend) goto L1; else goto L2;
 L2:
     if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
 L3:

 If this is a combined omp parallel loop, instead of the call to
 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
 If this is gimple_omp_for_combined_p loop, then instead of assigning
 V and iend in L0 we assign the first two _looptemp_ clause decls of the
 inner GIMPLE_OMP_FOR and V += STEP; and
 if (V cond iend) goto L1; else goto L2; are removed.

 For collapsed loops, given parameters:
   collapse(3)
   for (V1 = N11; V1 cond1 N12; V1 += STEP1)
     for (V2 = N21; V2 cond2 N22; V2 += STEP2)
       for (V3 = N31; V3 cond3 N32; V3 += STEP3)
         BODY;

 we generate pseudocode

     if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
     if (cond3 is <)
       adj = STEP3 - 1;
     else
       adj = STEP3 + 1;
     count3 = (adj + N32 - N31) / STEP3;
     if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
     if (cond2 is <)
       adj = STEP2 - 1;
     else
       adj = STEP2 + 1;
     count2 = (adj + N22 - N21) / STEP2;
     if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
     if (cond1 is <)
       adj = STEP1 - 1;
     else
       adj = STEP1 + 1;
     count1 = (adj + N12 - N11) / STEP1;
     count = count1 * count2 * count3;
     goto Z1;
 Z0:
     count = 0;
 Z1:
     more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
     if (more) goto L0; else goto L3;
 L0:
     V = istart0;
     T = V;
     V3 = N31 + (T % count3) * STEP3;
     T = T / count3;
     V2 = N21 + (T % count2) * STEP2;
     T = T / count2;
     V1 = N11 + T * STEP1;
     iend = iend0;
 L1:
     BODY;
     V += 1;
     if (V < iend) goto L10; else goto L2;
 L10:
     V3 += STEP3;
     if (V3 cond3 N32) goto L1; else goto L11;
 L11:
     V3 = N31;
     V2 += STEP2;
     if (V2 cond2 N22) goto L1; else goto L12;
 L12:
     V2 = N21;
     V1 += STEP1;
     goto L1;
 L2:
     if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
 L3:

References a, add_bb_to_loop(), add_loop(), add_phi_arg(), alloc_loop(), profile_probability::apply_scale(), boolean_type_node, BRANCH_EDGE, build1(), build2(), build4(), build_array_type_nelts(), build_call_expr(), build_clobber(), build_constructor(), build_fold_addr_expr, build_int_cst(), build_simple_mem_ref_loc(), builtin_decl_explicit(), CDI_DOMINATORS, cfun, CONSTRUCTOR_APPEND_ELT, omp_region::cont, copy_ssa_name(), create_empty_bb(), create_phi_node(), create_tmp_var, DECL_INITIAL, DECL_NAMELESS, DECL_P, EDGE_COUNT, omp_region::entry, omp_region::exit, EXIT_BLOCK_PTR_FOR_FN, expand_omp_build_assign(), expand_omp_for_init_counts(), expand_omp_for_init_vars(), expand_omp_for_ordered_loops(), expand_omp_ordered_source_sink(), extract_omp_for_update_vars(), FALLTHRU_EDGE, find_edge(), find_phi_with_arg_on_edge(), fold_build2, fold_build_pointer_plus, fold_convert, force_gimple_operand_gsi(), g, gcc_assert, get_immediate_dominator(), GF_OMP_FOR_KIND_FOR, GF_OMP_FOR_KIND_SIMD, ggc_alloc(), gimple_assign_lhs(), gimple_assign_rhs1(), gimple_bb(), gimple_build_assign(), gimple_build_call(), gimple_build_cond_empty(), gimple_build_omp_continue(), gimple_call_lhs(), gimple_call_set_lhs(), gimple_in_ssa_p(), gimple_omp_continue_control_def(), gimple_omp_continue_control_use(), gimple_omp_for_clauses(), gimple_omp_for_combined_into_p(), gimple_omp_for_combined_p(), gimple_omp_for_kind(), gimple_omp_return_lhs(), gimple_omp_return_nowait_p(), gimple_phi_arg_location_from_edge(), gimple_phi_result(), gsi_after_labels(), gsi_bb(), GSI_CONTINUE_LINKING, gsi_end_p(), gsi_insert_after(), gsi_insert_before(), gsi_last_bb(), gsi_last_nondebug_bb(), gsi_next(), gsi_prev(), gsi_remove(), GSI_SAME_STMT, gsi_start(), gsi_start_bb(), gsi_start_phis(), gsi_stmt(), profile_probability::guessed_always(), loop::header, i, integer_onep(), profile_probability::invert(), is_combined_parallel(), loop::latch, long_integer_type_node, long_long_unsigned_type_node, basic_block_def::loop_father, make_edge(), NULL, null_pointer_node, NULL_TREE, omp_adjust_chunk_size(), OMP_CLAUSE__CONDTEMP_, OMP_CLAUSE__LOOPTEMP_, OMP_CLAUSE__REDUCTEMP_, OMP_CLAUSE_CHAIN, OMP_CLAUSE_CODE, OMP_CLAUSE_DECL, OMP_CLAUSE_LASTPRIVATE, OMP_CLAUSE_LINEAR, OMP_CLAUSE_LINEAR_NO_COPYIN, OMP_CLAUSE_LINEAR_STEP, OMP_CLAUSE_LOCATION, omp_find_clause(), omp_privatize_by_reference(), gphi_iterator::phi(), PHI_ARG_DEF_FROM_EDGE, PHI_ARG_DEF_PTR_FROM_EDGE, phi_nodes(), phis, POINTER_TYPE_P, recompute_dominator(), release_ssa_name(), remove_bb_from_loops(), remove_edge(), set_immediate_dominator(), SET_USE, signed_type_for(), single_succ(), single_succ_edge(), size_int, size_zero_node, sizetype, split_block(), split_edge(), SSA_NAME_DEF_STMT, SSA_VAR_P, basic_block_def::succs, suppress_warning(), TREE_ADDRESSABLE, TREE_CODE, tree_int_cst_sgn(), TREE_STATIC, tree_to_uhwi(), TREE_TYPE, type(), TYPE_MIN_VALUE, TYPE_PRECISION, TYPE_SIZE_UNIT, TYPE_UNSIGNED, UNKNOWN_LOCATION, unshare_expr(), unsigned_type_node, useless_type_conversion_p(), vec_alloc(), virtual_operand_p(), and void_type_node.

Referenced by expand_omp_for().

◆ expand_omp_for_init_counts()

static void expand_omp_for_init_counts ( struct omp_for_data * fd,
gimple_stmt_iterator * gsi,
basic_block & entry_bb,
tree * counts,
basic_block & zero_iter1_bb,
int & first_zero_iter1,
basic_block & zero_iter2_bb,
int & first_zero_iter2,
basic_block & l2_dom_bb )
static
Helper function for expand_omp_{for_*,simd}.  If this is the outermost
of the combined collapse > 1 loop constructs, generate code like:
     if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
     if (cond3 is <)
       adj = STEP3 - 1;
     else
       adj = STEP3 + 1;
     count3 = (adj + N32 - N31) / STEP3;
     if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
     if (cond2 is <)
       adj = STEP2 - 1;
     else
       adj = STEP2 + 1;
     count2 = (adj + N22 - N21) / STEP2;
     if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
     if (cond1 is <)
       adj = STEP1 - 1;
     else
       adj = STEP1 + 1;
     count1 = (adj + N12 - N11) / STEP1;
     count = count1 * count2 * count3;
Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
     count = 0;
and set ZERO_ITER_BB to that bb.  If this isn't the outermost
of the combined loop constructs, just initialize COUNTS array
from the _looptemp_ clauses.  For loop nests with non-rectangular
loops, do this only for the rectangular loops.  Then pick
the loops which reference outer vars in their bound expressions
and the loops which they refer to and for this sub-nest compute
number of iterations.  For triangular loops use Faulhaber's formula,
otherwise as a fallback, compute by iterating the loops.
If e.g. the sub-nest is
     for (I = N11; I COND1 N12; I += STEP1)
     for (J = M21 * I + N21; J COND2 M22 * I + N22; J += STEP2)
     for (K = M31 * J + N31; K COND3 M32 * J + N32; K += STEP3)
do:
     COUNT = 0;
     for (tmpi = N11; tmpi COND1 N12; tmpi += STEP1)
     for (tmpj = M21 * tmpi + N21;
          tmpj COND2 M22 * tmpi + N22; tmpj += STEP2)
       {
         int tmpk1 = M31 * tmpj + N31;
         int tmpk2 = M32 * tmpj + N32;
         if (tmpk1 COND3 tmpk2)
           {
        if (COND3 is <)
          adj = STEP3 - 1;
        else
          adj = STEP3 + 1;
        COUNT += (adj + tmpk2 - tmpk1) / STEP3;
           }
       }
and finally multiply the counts of the rectangular loops not
in the sub-nest with COUNT.  Also, as counts[fd->last_nonrect]
store number of iterations of the loops from fd->first_nonrect
to fd->last_nonrect inclusive, i.e. the above COUNT multiplied
by the counts of rectangular loops not referenced in any non-rectangular
loops sandwitched in between those.   
NOTE: It *could* be better to moosh all of the BBs together,
creating one larger BB with all the computation and the unexpected
jump at the end.  I.e.

bool zero3, zero2, zero1, zero;

zero3 = N32 c3 N31;
count3 = (N32 - N31) /[cl] STEP3;
zero2 = N22 c2 N21;
count2 = (N22 - N21) /[cl] STEP2;
zero1 = N12 c1 N11;
count1 = (N12 - N11) /[cl] STEP1;
zero = zero3 || zero2 || zero1;
count = count1 * count2 * count3;
if (__builtin_expect(zero, false)) goto zero_iter_bb;

After all, we expect the zero=false, and thus we expect to have to
evaluate all of the comparison expressions, so short-circuiting
oughtn't be a win.  Since the condition isn't protecting a
denominator, we're not concerned about divide-by-zero, so we can
fully evaluate count even if a numerator turned out to be wrong.

It seems like putting this all together would create much better
scheduling opportunities, and less pressure on the chip's branch
predictor.   

References add_bb_to_loop(), boolean_type_node, build_int_cst(), build_one_cst(), build_zero_cst(), CDI_DOMINATORS, cfun, create_empty_bb(), create_tmp_reg(), expand_omp_build_assign(), expand_omp_build_cond(), find_edge(), fold_binary, fold_build1, fold_build2, fold_build_pointer_plus, fold_convert, force_gimple_operand_gsi(), gcc_assert, ggc_alloc(), gimple_build_assign(), gimple_in_ssa_p(), gimple_omp_for_clauses(), gimple_omp_for_combined_into_p(), gsi_after_labels(), gsi_bb(), gsi_insert_before(), gsi_last_nondebug_bb(), gsi_prev(), GSI_SAME_STMT, gsi_stmt(), profile_probability::guessed(), i, integer_one_node, integer_onep(), integer_zerop(), last, last_nondebug_stmt(), profile_probability::likely(), basic_block_def::loop_father, make_edge(), NULL, NULL_TREE, OMP_CLAUSE__LOOPTEMP_, OMP_CLAUSE_CHAIN, OMP_CLAUSE_DECL, omp_find_clause(), POINTER_TYPE_P, remove_edge(), set_immediate_dominator(), signed_type_for(), split_block(), SSA_VAR_P, TREE_CODE, TREE_TYPE, TYPE_UNSIGNED, profile_probability::unlikely(), unshare_expr(), and profile_probability::very_unlikely().

Referenced by expand_omp_for_generic(), expand_omp_for_static_chunk(), expand_omp_for_static_nochunk(), expand_omp_simd(), expand_omp_taskloop_for_inner(), and expand_omp_taskloop_for_outer().

◆ expand_omp_for_init_vars()

static void expand_omp_for_init_vars ( struct omp_for_data * fd,
gimple_stmt_iterator * gsi,
tree * counts,
tree * nonrect_bounds,
gimple * inner_stmt,
tree startvar )
static
Helper function for expand_omp_{for_*,simd}.  Generate code like:
     T = V;
     V3 = N31 + (T % count3) * STEP3;
     T = T / count3;
     V2 = N21 + (T % count2) * STEP2;
     T = T / count2;
     V1 = N11 + T * STEP1;
if this loop doesn't have an inner loop construct combined with it.
If it does have an inner loop construct combined with it and the
iteration count isn't known constant, store values from counts array
into its _looptemp_ temporaries instead.
For non-rectangular loops (between fd->first_nonrect and fd->last_nonrect
inclusive), use the count of all those loops together, and either
find quadratic etc. equation roots, or as a fallback, do:
     COUNT = 0;
     for (tmpi = N11; tmpi COND1 N12; tmpi += STEP1)
     for (tmpj = M21 * tmpi + N21;
          tmpj COND2 M22 * tmpi + N22; tmpj += STEP2)
       {
         int tmpk1 = M31 * tmpj + N31;
         int tmpk2 = M32 * tmpj + N32;
         if (tmpk1 COND3 tmpk2)
           {
        if (COND3 is <)
          adj = STEP3 - 1;
        else
          adj = STEP3 + 1;
        int temp = (adj + tmpk2 - tmpk1) / STEP3;
        if (COUNT + temp > T)
          {
            V1 = tmpi;
            V2 = tmpj;
            V3 = tmpk1 + (T - COUNT) * STEP3;
            goto done;
          }
        else
          COUNT += temp;
           }
       }
     done:;
but for optional innermost or outermost rectangular loops that aren't
referenced by other loop expressions keep doing the division/modulo.   

References add_bb_to_loop(), boolean_false_node, boolean_true_node, boolean_type_node, build_int_cst(), build_one_cst(), build_real(), build_zero_cst(), CDI_DOMINATORS, cfun, count, create_empty_bb(), create_tmp_reg(), create_tmp_var, dconst2, DECL_P, double_type_node, expand_omp_build_assign(), expand_omp_build_cond(), find_edge(), fold_build1, fold_build2, fold_build_pointer_plus, fold_convert, force_gimple_operand_gsi(), gcc_assert, gcc_unreachable, ggc_alloc(), gimple_build_assign(), gimple_build_call_internal(), gimple_build_cond(), gimple_build_nop(), gimple_call_set_lhs(), gimple_omp_for_clauses(), gimple_omp_for_combined_p(), gimple_omp_taskreg_clauses(), gsi_after_labels(), gsi_bb(), GSI_CONTINUE_LINKING, gsi_end_p(), gsi_insert_after(), gsi_insert_before(), gsi_last_bb(), GSI_NEW_STMT, gsi_prev(), GSI_SAME_STMT, gsi_stmt(), profile_probability::guessed(), i, integer_one_node, integer_onep(), integer_zerop(), last_nondebug_stmt(), profile_probability::likely(), long_long_integer_type_node, long_long_unsigned_type_node, make_edge(), NULL, NULL_TREE, OMP_CLAUSE__LOOPTEMP_, OMP_CLAUSE_CHAIN, OMP_CLAUSE_DECL, omp_find_clause(), operation_could_trap_p(), optab_handler(), POINTER_TYPE_P, remove_edge(), set_immediate_dominator(), signed_type_for(), split_block(), TREE_ADDRESSABLE, TREE_CODE, TREE_TYPE, TYPE_MODE, TYPE_UNSIGNED, profile_probability::unlikely(), unshare_expr(), profile_probability::very_likely(), and profile_probability::very_unlikely().

Referenced by expand_omp_for_generic(), expand_omp_for_static_chunk(), expand_omp_for_static_nochunk(), expand_omp_simd(), expand_omp_taskloop_for_inner(), and expand_omp_taskloop_for_outer().

◆ expand_omp_for_ordered_loops()

◆ expand_omp_for_static_chunk()

static void expand_omp_for_static_chunk ( struct omp_region * region,
struct omp_for_data * fd,
gimple * inner_stmt )
static
A subroutine of expand_omp_for.  Generate code for a parallel
  loop with static schedule and a specified chunk size.  Given
  parameters:

       for (V = N1; V cond N2; V += STEP) BODY;

  where COND is "<" or ">", we generate pseudocode

       if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
       if (cond is <)
         adj = STEP - 1;
       else
         adj = STEP + 1;
       if ((__typeof (V)) -1 > 0 && cond is >)
         n = -(adj + N2 - N1) / -STEP;
       else
         n = (adj + N2 - N1) / STEP;
       trip = 0;
       V = threadid * CHUNK * STEP + N1;  -- this extra definition of V is
                                      here so that V is defined
                                      if the loop is not entered
   L0:
       s0 = (trip * nthreads + threadid) * CHUNK;
       e0 = min (s0 + CHUNK, n);
       if (s0 < n) goto L1; else goto L4;
   L1:
       V = s0 * STEP + N1;
       e = e0 * STEP + N1;
   L2:
       BODY;
       V += STEP;
       if (V cond e) goto L2; else goto L3;
   L3:
       trip += 1;
       goto L0;
   L4:

References a, add_loop(), add_phi_arg(), alloc_loop(), boolean_type_node, BRANCH_EDGE, build2(), build_call_expr(), build_fold_addr_expr, build_int_cst(), build_int_cstu(), build_simple_mem_ref_loc(), builtin_decl_explicit(), CDI_DOMINATORS, cfun, omp_region::cont, copy_ssa_name(), create_phi_node(), create_tmp_reg(), create_tmp_var, DECL_P, EDGE_COUNT, omp_region::entry, omp_region::exit, expand_omp_build_assign(), expand_omp_build_cond(), expand_omp_for_init_counts(), expand_omp_for_init_vars(), extract_omp_for_update_vars(), FALLTHRU_EDGE, find_edge(), find_lastprivate_looptemp(), find_phi_with_arg_on_edge(), fold_binary, fold_build1, fold_build2, fold_build_pointer_plus, fold_convert, force_gimple_operand_gsi(), g, gcc_assert, gcc_unreachable, GF_OMP_FOR_KIND_DISTRIBUTE, GF_OMP_FOR_KIND_FOR, ggc_alloc(), gimple_assign_lhs(), gimple_assign_rhs1(), gimple_build_assign(), gimple_build_call(), gimple_build_cond_empty(), gimple_call_set_lhs(), gimple_in_ssa_p(), gimple_omp_continue_control_def(), gimple_omp_continue_control_use(), gimple_omp_for_clauses(), gimple_omp_for_combined_into_p(), gimple_omp_for_combined_p(), gimple_omp_for_kind(), gimple_omp_parallel_clauses(), gimple_omp_return_lhs(), gimple_omp_return_nowait_p(), gimple_phi_arg_def(), gimple_phi_arg_location_from_edge(), gimple_phi_result(), gsi_after_labels(), GSI_CONTINUE_LINKING, gsi_end_p(), gsi_for_stmt(), gsi_insert_after(), gsi_insert_before(), gsi_last_bb(), gsi_last_nondebug_bb(), gsi_next(), gsi_none(), gsi_prev(), gsi_remove(), GSI_SAME_STMT, gsi_start_bb(), gsi_start_phis(), gsi_stmt(), loop::header, HOST_WIDE_INT_1U, i, integer_one_node, integer_onep(), last_nondebug_stmt(), loop::latch, long_integer_type_node, basic_block_def::loop_father, make_edge(), make_ssa_name(), NULL, null_pointer_node, NULL_TREE, omp_adjust_chunk_size(), omp_build_barrier(), OMP_CLAUSE__CONDTEMP_, OMP_CLAUSE__LOOPTEMP_, OMP_CLAUSE__REDUCTEMP_, OMP_CLAUSE_CHAIN, OMP_CLAUSE_CODE, OMP_CLAUSE_DECL, OMP_CLAUSE_LINEAR, OMP_CLAUSE_LINEAR_NO_COPYIN, OMP_CLAUSE_LINEAR_STEP, OMP_CLAUSE_LOCATION, omp_find_clause(), omp_privatize_by_reference(), operand_equal_p(), gphi_iterator::phi(), PHI_ARG_DEF_FROM_EDGE, POINTER_TYPE_P, recompute_dominator(), redirect_edge_and_branch(), redirect_edge_var_map_clear(), redirect_edge_var_map_def(), redirect_edge_var_map_location(), redirect_edge_var_map_result(), redirect_edge_var_map_vector(), release_ssa_name(), remove_edge(), remove_phi_node(), set_immediate_dominator(), signed_type_for(), single_pred(), single_pred_p(), single_succ(), single_succ_edge(), sizetype, split_block(), split_edge(), SSA_NAME_DEF_STMT, TREE_ADDRESSABLE, TREE_CODE, tree_int_cst_equal(), tree_int_cst_sgn(), tree_to_uhwi(), TREE_TYPE, type(), TYPE_PRECISION, TYPE_SIZE_UNIT, TYPE_UNSIGNED, UNKNOWN_LOCATION, unshare_expr(), useless_type_conversion_p(), profile_probability::very_likely(), and profile_probability::very_unlikely().

Referenced by expand_omp_for().

◆ expand_omp_for_static_nochunk()

static void expand_omp_for_static_nochunk ( struct omp_region * region,
struct omp_for_data * fd,
gimple * inner_stmt )
static
A subroutine of expand_omp_for.  Generate code for a parallel
  loop with static schedule and no specified chunk size.  Given
  parameters:

       for (V = N1; V cond N2; V += STEP) BODY;

  where COND is "<" or ">", we generate pseudocode

       if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
       if (cond is <)
         adj = STEP - 1;
       else
         adj = STEP + 1;
       if ((__typeof (V)) -1 > 0 && cond is >)
         n = -(adj + N2 - N1) / -STEP;
       else
         n = (adj + N2 - N1) / STEP;
       q = n / nthreads;
       tt = n % nthreads;
       if (threadid < tt) goto L3; else goto L4;
   L3:
       tt = 0;
       q = q + 1;
   L4:
       s0 = q * threadid + tt;
       e0 = s0 + q;
       V = s0 * STEP + N1;
       if (s0 >= e0) goto L2; else goto L0;
   L0:
       e = e0 * STEP + N1;
   L1:
       BODY;
       V += STEP;
       if (V cond e) goto L1;
   L2:

References a, add_loop(), add_phi_arg(), alloc_loop(), profile_probability::apply_scale(), boolean_false_node, boolean_type_node, BRANCH_EDGE, build2(), build_call_expr(), build_fold_addr_expr, build_int_cst(), build_int_cstu(), build_simple_mem_ref_loc(), builtin_decl_explicit(), builtin_decl_implicit(), CDI_DOMINATORS, cfun, omp_region::cont, create_tmp_reg(), create_tmp_var, DECL_P, EDGE_COUNT, omp_region::entry, omp_region::exit, expand_omp_build_assign(), expand_omp_build_cond(), expand_omp_for_init_counts(), expand_omp_for_init_vars(), expand_omp_scantemp_alloc(), extract_omp_for_update_vars(), FALLTHRU_EDGE, find_edge(), find_lastprivate_looptemp(), fold_binary, fold_build1, fold_build2, fold_build_pointer_plus, fold_convert, force_gimple_operand_gsi(), g, gcc_assert, gcc_unreachable, GF_OMP_FOR_KIND_DISTRIBUTE, GF_OMP_FOR_KIND_FOR, ggc_alloc(), gimple_assign_lhs(), gimple_assign_rhs1(), gimple_build_assign(), gimple_build_call(), gimple_build_cond(), gimple_build_cond_empty(), gimple_call_set_lhs(), gimple_in_ssa_p(), gimple_omp_continue_control_def(), gimple_omp_continue_control_use(), gimple_omp_for_clauses(), gimple_omp_for_combined_into_p(), gimple_omp_for_combined_p(), gimple_omp_for_kind(), gimple_omp_parallel_clauses(), gimple_omp_return_lhs(), gimple_omp_return_nowait_p(), gimple_phi_arg_def(), gsi_after_labels(), GSI_CONTINUE_LINKING, gsi_end_p(), gsi_for_stmt(), gsi_insert_after(), gsi_insert_before(), gsi_last_bb(), gsi_last_nondebug_bb(), gsi_next(), gsi_none(), gsi_prev(), gsi_remove(), GSI_SAME_STMT, gsi_start_bb(), gsi_start_phis(), gsi_stmt(), profile_probability::guessed_always(), loop::header, HOST_WIDE_INT_1U, integer_one_node, integer_onep(), integer_type_node, loop::latch, long_integer_type_node, long_long_integer_type_node, basic_block_def::loop_father, make_edge(), NULL, null_pointer_node, NULL_TREE, omp_build_barrier(), OMP_CLAUSE__CONDTEMP_, OMP_CLAUSE__LOOPTEMP_, OMP_CLAUSE__REDUCTEMP_, OMP_CLAUSE__SCANTEMP_, OMP_CLAUSE__SCANTEMP__ALLOC, OMP_CLAUSE__SCANTEMP__CONTROL, OMP_CLAUSE_CHAIN, OMP_CLAUSE_CODE, OMP_CLAUSE_DECL, OMP_CLAUSE_LINEAR, OMP_CLAUSE_LINEAR_NO_COPYIN, OMP_CLAUSE_LINEAR_STEP, OMP_CLAUSE_LOCATION, omp_find_clause(), omp_privatize_by_reference(), POINTER_TYPE_P, ptr_type_node, recompute_dominator(), redirect_edge_and_branch(), release_ssa_name(), remove_edge(), set_immediate_dominator(), signed_type_for(), single_pred(), single_succ(), size_int, sizetype, split_block(), split_edge(), SSA_NAME_DEF_STMT, basic_block_def::succs, TREE_ADDRESSABLE, TREE_CODE, tree_int_cst_sgn(), tree_to_uhwi(), TREE_TYPE, type(), TYPE_ALIGN, TYPE_ALIGN_UNIT, TYPE_PRECISION, TYPE_SIZE_UNIT, TYPE_UNSIGNED, UNKNOWN_LOCATION, unshare_expr(), useless_type_conversion_p(), profile_probability::very_likely(), and profile_probability::very_unlikely().

Referenced by expand_omp_for().

◆ expand_omp_ordered_sink()

◆ expand_omp_ordered_source()

static void expand_omp_ordered_source ( gimple_stmt_iterator * gsi,
struct omp_for_data * fd,
tree * counts,
location_t loc )
static

◆ expand_omp_ordered_source_sink()

◆ expand_omp_regimplify_p()

static tree expand_omp_regimplify_p ( tree * tp,
int * walk_subtrees,
void *  )
static
Callback for expand_omp_build_assign.  Return non-NULL if *tp needs to be
regimplified.   

References DECL_HAS_VALUE_EXPR_P, DECL_P, ggc_alloc(), NULL_TREE, recompute_tree_invariant_for_addr_expr(), TREE_CODE, TYPE_P, and VAR_P.

Referenced by expand_omp_build_assign(), expand_omp_build_cond(), expand_omp_simd(), and extract_omp_for_update_vars().

◆ expand_omp_scantemp_alloc()

static tree expand_omp_scantemp_alloc ( tree clauses,
tree ptr,
unsigned HOST_WIDE_INT sz,
unsigned HOST_WIDE_INT alloc_align,
tree cnt,
gimple_stmt_iterator * gsi,
bool alloc )
static
Helper function for expand_omp_for_static_nochunk.  If PTR is NULL,
compute needed allocation size.  If !ALLOC of team allocations,
if ALLOC of thread allocation.  SZ is the initial needed size for
other purposes, ALLOC_ALIGN guaranteed alignment of allocation in bytes,
CNT number of elements of each array, for !ALLOC this is
omp_get_num_threads (), for ALLOC number of iterations handled by the
current thread.  If PTR is non-NULL, it is the start of the allocation
and this routine shall assign to OMP_CLAUSE_DECL (c) of those _scantemp_
clauses pointers to the corresponding arrays.   

References build_int_cst(), expand_omp_build_assign(), fold_build2, fold_convert, ggc_alloc(), least_bit_hwi(), MIN, NULL_TREE, OMP_CLAUSE__SCANTEMP_, OMP_CLAUSE__SCANTEMP__ALLOC, OMP_CLAUSE__SCANTEMP__CONTROL, OMP_CLAUSE_CHAIN, OMP_CLAUSE_CODE, OMP_CLAUSE_DECL, pointer_sized_int_node, ptr_type_node, ROUND_UP, size_binop, size_int, tree_fits_uhwi_p(), tree_to_uhwi(), TREE_TYPE, TYPE_ALIGN_UNIT, and TYPE_SIZE_UNIT.

Referenced by expand_omp_for_static_nochunk().

◆ expand_omp_sections()

static void expand_omp_sections ( struct omp_region * region)
static
Expand code for an OpenMP sections directive.  In pseudo code, we generate

    v = GOMP_sections_start (n);
L0:
    switch (v)
      {
      case 0:
        goto L2;
      case 1:
        section 1;
        goto L1;
      case 2:
        ...
      case n:
        ...
      default:
        abort ();
      }
L1:
    v = GOMP_sections_next ();
    goto L0;
L2:
    reduction;

If this is a combined parallel sections, replace the call to
GOMP_sections_start with call to GOMP_sections_next.   

References add_bb_to_loop(), build2(), build_case_label(), build_fold_addr_expr, build_int_cst(), build_one_cst(), builtin_decl_explicit(), CDI_DOMINATORS, omp_region::cont, create_empty_bb(), create_tmp_var, current_loops, EDGE_COUNT, EDGE_SUCC, omp_region::entry, omp_region::exit, expand_omp_build_assign(), FOR_EACH_EDGE, g, gcc_assert, ggc_alloc(), gimple_assign_lhs(), gimple_assign_rhs1(), gimple_block_label(), gimple_build_call(), gimple_build_switch(), gimple_call_set_lhs(), gimple_omp_continue_control_def(), gimple_omp_continue_control_use(), gimple_omp_return_lhs(), gimple_omp_return_nowait_p(), gimple_omp_section_last_p(), gimple_omp_sections_clauses(), gimple_omp_sections_control(), GSI_CONTINUE_LINKING, gsi_end_p(), gsi_for_stmt(), gsi_insert_after(), gsi_insert_before(), gsi_last_nondebug_bb(), gsi_none(), gsi_remove(), GSI_SAME_STMT, gsi_start_bb(), gsi_stmt(), i, omp_region::inner, is_combined_parallel(), last_nondebug_stmt(), make_edge(), omp_region::next, NULL, null_pointer_node, NULL_TREE, OMP_CLAUSE__CONDTEMP_, OMP_CLAUSE__REDUCTEMP_, OMP_CLAUSE_CHAIN, OMP_CLAUSE_CODE, OMP_CLAUSE_DECL, OMP_CLAUSE_LASTPRIVATE, OMP_CLAUSE_LASTPRIVATE_CONDITIONAL, omp_find_clause(), release_ssa_name(), set_immediate_dominator(), si, single_pred(), single_pred_p(), single_succ(), single_succ_edge(), SSA_NAME_DEF_STMT, TREE_ADDRESSABLE, TREE_CODE, tree_to_uhwi(), TREE_TYPE, omp_region::type, TYPE_SIZE_UNIT, and unsigned_type_node.

Referenced by expand_omp().

◆ expand_omp_simd()

static void expand_omp_simd ( struct omp_region * region,
struct omp_for_data * fd )
static
A subroutine of expand_omp_for.  Generate code for a simd non-worksharing
loop.  Given parameters:

     for (V = N1; V cond N2; V += STEP) BODY;

where COND is "<" or ">", we generate pseudocode

     V = N1;
     goto L1;
 L0:
     BODY;
     V += STEP;
 L1:
     if (V cond N2) goto L0; else goto L2;
 L2:

 For collapsed loops, emit the outer loops as scalar
 and only try to vectorize the innermost loop.   

References add_bb_to_loop(), add_loop(), alloc_loop(), profile_probability::apply_scale(), boolean_type_node, BRANCH_EDGE, build2(), build_call_expr_internal_loc(), build_int_cst(), build_one_cst(), build_zero_cst(), CDI_DOMINATORS, cfun, omp_region::cont, create_empty_bb(), create_tmp_var, DECL_P, loop::dont_vectorize, EDGE_COUNT, EDGE_SUCC, omp_region::entry, omp_region::exit, expand_omp_build_assign(), expand_omp_for_init_counts(), expand_omp_for_init_vars(), expand_omp_regimplify_p(), FALLTHRU_EDGE, find_edge(), fold_build1, fold_build2, fold_build_pointer_plus, fold_convert, force_gimple_operand_gsi(), loop::force_vectorize, g, gcc_assert, ggc_alloc(), gimple_build_assign(), gimple_build_call_internal(), gimple_build_cond(), gimple_build_cond_empty(), gimple_call_set_lhs(), gimple_cond_lhs_ptr(), gimple_cond_rhs_ptr(), gimple_in_ssa_p(), gimple_omp_for_clauses(), gimple_omp_for_combined_into_p(), gimple_regimplify_operands(), gsi_after_labels(), gsi_bb(), GSI_CONTINUE_LINKING, gsi_for_stmt(), gsi_insert_after(), gsi_insert_before(), gsi_last_bb(), gsi_last_nondebug_bb(), GSI_NEW_STMT, gsi_prev(), gsi_remove(), GSI_SAME_STMT, gsi_start_bb(), gsi_stmt(), profile_probability::guessed_always(), loop::header, i, INT_MAX, integer_nonzerop(), integer_onep(), integer_zerop(), profile_probability::invert(), last_nondebug_stmt(), loop::latch, basic_block_def::loop_father, make_edge(), MIN, NULL, NULL_TREE, offset, OMP_CLAUSE__CONDTEMP_, OMP_CLAUSE__LOOPTEMP_, OMP_CLAUSE__SIMDUID_, OMP_CLAUSE__SIMDUID__DECL, OMP_CLAUSE__SIMT_, OMP_CLAUSE_CHAIN, OMP_CLAUSE_DECL, OMP_CLAUSE_IF, OMP_CLAUSE_IF_EXPR, OMP_CLAUSE_SAFELEN, OMP_CLAUSE_SAFELEN_EXPR, OMP_CLAUSE_SIMDLEN, OMP_CLAUSE_SIMDLEN_EXPR, omp_find_clause(), omp_max_simt_vf(), OPTION_SET_P, POINTER_TYPE_P, poly_int_tree_p(), redirect_edge_succ(), remove_edge(), loop::safelen, set_immediate_dominator(), signed_type_for(), loop::simdlen, loop::simduid, single_succ(), single_succ_edge(), split_block(), split_edge(), basic_block_def::succs, TREE_ADDRESSABLE, TREE_CODE, tree_fits_uhwi_p(), tree_int_cst_sgn(), tree_to_uhwi(), TREE_TYPE, type(), TYPE_UNSIGNED, UNKNOWN_LOCATION, unshare_expr(), unsigned_type_for(), unsigned_type_node, and walk_tree.

Referenced by expand_omp_for().

◆ expand_omp_single()

static void expand_omp_single ( struct omp_region * region)
static
Expand code for an OpenMP single or scope directive.  We've already expanded
much of the code, here we simply place the GOMP_barrier call.   

References omp_region::entry, omp_region::exit, gcc_assert, ggc_alloc(), gimple_omp_return_lhs(), gimple_omp_return_nowait_p(), gsi_insert_after(), gsi_last_nondebug_bb(), gsi_remove(), GSI_SAME_STMT, gsi_stmt(), NULL, omp_build_barrier(), si, and single_succ_edge().

Referenced by expand_omp().

◆ expand_omp_synch()

static void expand_omp_synch ( struct omp_region * region)
static
Generic expansion for OpenMP synchronization directives: master,
ordered and critical.  All we need to do here is remove the entry
and exit markers for REGION.   

References omp_region::entry, omp_region::exit, expand_omp_taskreg(), gcc_assert, ggc_alloc(), gimple_omp_teams_host(), gsi_last_nondebug_bb(), gsi_remove(), gsi_stmt(), si, and single_succ_edge().

Referenced by expand_omp().

◆ expand_omp_target()

static void expand_omp_target ( struct omp_region * region)
static
Expand the GIMPLE_OMP_TARGET starting at REGION.   

References add_bb_to_loop(), cgraph_node::add_new_function(), adjust_context_and_scope(), assign_assembler_name_if_needed(), BLOCK_SUPERCONTEXT, BLOCK_VARS, boolean_type_node, build1(), build2(), build_decl(), build_fold_addr_expr, build_int_cst(), build_zero_cst(), builtin_decl_explicit(), CDI_DOMINATORS, cfun, changed, cleanup_tree_cfg(), clone_function_name(), copy_list(), create_empty_bb(), create_tmp_var, current_function_decl, DECL_ARG_TYPE, DECL_ARGUMENTS, DECL_ARTIFICIAL, DECL_ASSEMBLER_NAME_SET_P, DECL_ATTRIBUTES, DECL_CHAIN, DECL_CONTEXT, DECL_EXTERNAL, DECL_FUNCTION_SPECIFIC_OPTIMIZATION, DECL_FUNCTION_SPECIFIC_TARGET, DECL_FUNCTION_VERSIONED, DECL_IGNORED_P, DECL_INITIAL, DECL_NAME, DECL_NAMELESS, DECL_PRESERVE_P, DECL_RESULT, DECL_SAVED_TREE, DECL_SOURCE_LOCATION, DECL_STRUCT_FUNCTION, DECL_UNINLINABLE, dump_file, dump_flags, dump_function_header(), dump_function_to_file(), omp_region::entry, omp_region::exit, varpool_node::finalize_decl(), basic_block_def::flags, fold_build1, fold_convert, fold_convert_loc(), FOR_EACH_BB_FN, force_gimple_operand_gsi(), g, gcc_assert, gcc_checking_assert, gcc_unreachable, cgraph_node::get(), cgraph_node::get_create(), get_identifier(), get_target_arguments(), GF_OMP_TARGET_KIND_DATA, GF_OMP_TARGET_KIND_ENTER_DATA, GF_OMP_TARGET_KIND_EXIT_DATA, GF_OMP_TARGET_KIND_OACC_DATA, GF_OMP_TARGET_KIND_OACC_DATA_KERNELS, GF_OMP_TARGET_KIND_OACC_DECLARE, GF_OMP_TARGET_KIND_OACC_ENTER_DATA, GF_OMP_TARGET_KIND_OACC_EXIT_DATA, GF_OMP_TARGET_KIND_OACC_HOST_DATA, GF_OMP_TARGET_KIND_OACC_KERNELS, GF_OMP_TARGET_KIND_OACC_PARALLEL, GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_GANG_SINGLE, GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_PARALLELIZED, GF_OMP_TARGET_KIND_OACC_SERIAL, GF_OMP_TARGET_KIND_OACC_UPDATE, GF_OMP_TARGET_KIND_REGION, GF_OMP_TARGET_KIND_UPDATE, ggc_alloc(), gimple_assign_lhs(), gimple_assign_rhs1(), gimple_block(), gimple_boolify(), gimple_build_assign(), gimple_build_call_internal(), gimple_build_call_vec(), gimple_build_cond_empty(), gimple_build_return(), gimple_in_ssa_p(), gimple_location(), gimple_num_ops(), gimple_omp_target_child_fn(), gimple_omp_target_clauses(), gimple_omp_target_data_arg(), gimple_omp_target_kind(), gimple_purge_dead_eh_edges(), gimple_set_body(), gimple_set_location(), gimplify_function_tree(), gsi_bb(), GSI_CONTINUE_LINKING, gsi_end_p(), gsi_for_stmt(), gsi_insert_after(), gsi_insert_before(), gsi_last_bb(), gsi_last_nondebug_bb(), gsi_next(), gsi_prev(), gsi_remove(), GSI_SAME_STMT, gsi_start_bb(), gsi_stmt(), integer_one_node, integer_type_node, integer_zero_node, is_gimple_omp_oacc(), is_gimple_omp_offloaded(), last_nondebug_stmt(), lookup_attribute(), LOOPS_NEED_FIXUP, loops_state_satisfies_p(), make_edge(), make_node(), mark_loops_in_oacc_kernels_region(), move_sese_region_to_fn(), NULL, NULL_TREE, oacc_launch_pack(), oacc_replace_fn_attrib(), oacc_set_fn_attrib(), offload_funcs, symtab_node::offloadable, omp_any_child_fn_dumped, OMP_CLAUSE_ASYNC, OMP_CLAUSE_ASYNC_EXPR, OMP_CLAUSE_CHAIN, OMP_CLAUSE_CODE, OMP_CLAUSE_DECL, OMP_CLAUSE_DEPEND, OMP_CLAUSE_DEVICE, OMP_CLAUSE_DEVICE_ANCESTOR, OMP_CLAUSE_DEVICE_ID, OMP_CLAUSE_IF, OMP_CLAUSE_IF_EXPR, OMP_CLAUSE_IN_REDUCTION, OMP_CLAUSE_LOCATION, OMP_CLAUSE_NOWAIT, OMP_CLAUSE_SELF, OMP_CLAUSE_SELF_EXPR, OMP_CLAUSE_WAIT, OMP_CLAUSE_WAIT_EXPR, omp_find_clause(), cgraph_node::parallelized_function, pop_cfun(), ptr_type_node, push_cfun(), cgraph_edge::rebuild_edges(), remove_attribute(), remove_edge(), set_immediate_dominator(), single_succ(), single_succ_edge(), size_binop, size_int, size_zero_node, split_block(), split_block_after_labels(), wi::to_wide(), TREE_CHAIN, TREE_CODE, tree_cons(), TREE_INT_CST_LOW, TREE_OPERAND, TREE_PUBLIC, TREE_READONLY, TREE_STATIC, TREE_TYPE, TREE_USED, TREE_VEC_ELT, TYPE_DOMAIN, TYPE_MAX_VALUE, UNKNOWN_LOCATION, unsigned_type_node, VAR_P, vec2chain(), vec_safe_length(), vec_safe_push(), vec_safe_truncate(), verify_loop_structure(), and void_type_node.

Referenced by expand_omp().

◆ expand_omp_taskloop_for_inner()

static void expand_omp_taskloop_for_inner ( struct omp_region * region,
struct omp_for_data * fd,
gimple * inner_stmt )
static
Taskloop construct is represented after gimplification with
two GIMPLE_OMP_FOR constructs with GIMPLE_OMP_TASK sandwiched
in between them.  This routine expands the inner GIMPLE_OMP_FOR.
GOMP_taskloop{,_ull} function arranges for each task to be given just
a single range of iterations.   

References add_loop(), alloc_loop(), profile_probability::always(), boolean_type_node, BRANCH_EDGE, build2(), CDI_DOMINATORS, omp_region::cont, DECL_P, EDGE_COUNT, omp_region::entry, omp_region::exit, expand_omp_for_init_counts(), expand_omp_for_init_vars(), extract_omp_for_update_vars(), FALLTHRU_EDGE, find_edge(), fold_build2, fold_build_pointer_plus, fold_convert, force_gimple_operand_gsi(), gcc_assert, ggc_alloc(), gimple_build_assign(), gimple_build_cond_empty(), gimple_omp_continue_control_def(), gimple_omp_continue_control_use(), gimple_omp_for_clauses(), gimple_omp_for_combined_p(), gsi_bb(), GSI_CONTINUE_LINKING, gsi_for_stmt(), gsi_insert_after(), gsi_insert_before(), gsi_last_nondebug_bb(), gsi_remove(), GSI_SAME_STMT, gsi_stmt(), loop::header, integer_one_node, loop::latch, long_long_unsigned_type_node, make_edge(), NULL, NULL_TREE, OMP_CLAUSE__LOOPTEMP_, OMP_CLAUSE_CHAIN, OMP_CLAUSE_DECL, omp_find_clause(), omp_region::outer, POINTER_TYPE_P, recompute_dominator(), remove_edge(), remove_edge_and_dominated_blocks(), set_immediate_dominator(), signed_type_for(), basic_block_def::succs, TREE_ADDRESSABLE, TREE_CODE, tree_int_cst_sgn(), TREE_TYPE, type(), TYPE_MIN_VALUE, TYPE_UNSIGNED, and useless_type_conversion_p().

Referenced by expand_omp_for().

◆ expand_omp_taskloop_for_outer()

◆ expand_omp_taskreg()

static void expand_omp_taskreg ( struct omp_region * region)
static
Expand the OpenMP parallel or task directive starting at REGION.   

References cgraph_node::add_new_function(), adjust_context_and_scope(), assign_assembler_name_if_needed(), BLOCK_VARS, BRANCH_EDGE, CDI_DOMINATORS, cfun, changed, cleanup_tree_cfg(), omp_region::cont, current_function_decl, DECL_ARGUMENTS, DECL_ASSEMBLER_NAME_SET_P, DECL_CHAIN, DECL_CONTEXT, DECL_EXTERNAL, DECL_INITIAL, DECL_SAVED_TREE, DECL_STRUCT_FUNCTION, dump_file, dump_flags, dump_function_header(), dump_function_to_file(), omp_region::entry, omp_region::exit, expand_parallel_call(), expand_task_call(), expand_taskwait_call(), expand_teams_call(), FALLTHRU_EDGE, varpool_node::finalize_decl(), basic_block_def::flags, FOR_EACH_BB_FN, gcc_assert, cgraph_node::get_create(), ggc_alloc(), gimple_assign_lhs(), gimple_assign_rhs1(), gimple_assign_set_rhs1(), gimple_block(), gimple_build_return(), gimple_in_ssa_p(), gimple_num_ops(), gimple_omp_set_subcode(), gimple_omp_task_taskwait_p(), gimple_omp_taskreg_child_fn(), gimple_omp_taskreg_data_arg(), gimple_purge_dead_eh_edges(), gimple_set_body(), gsi_end_p(), gsi_insert_after(), gsi_last_nondebug_bb(), gsi_next(), gsi_remove(), GSI_SAME_STMT, gsi_start_bb(), gsi_stmt(), init_ssa_operands(), init_tree_ssa(), is_combined_parallel(), last_nondebug_stmt(), LOOPS_NEED_FIXUP, loops_state_satisfies_p(), make_edge(), move_sese_region_to_fn(), NULL, NULL_TREE, omp_any_child_fn_dumped, optimize_omp_library_calls(), cgraph_node::parallelized_function, pop_cfun(), push_cfun(), cgraph_edge::rebuild_edges(), remove_edge(), remove_edge_and_dominated_blocks(), set_immediate_dominator(), single_succ(), single_succ_edge(), single_succ_p(), split_block(), SSA_NAME_VAR, TODO_update_ssa, TREE_CODE, TREE_OPERAND, TREE_STATIC, TREE_USED, update_max_bb_count(), update_ssa(), update_stmt(), VAR_P, vec2chain(), vec_safe_length(), vec_safe_truncate(), verify_loop_structure(), and omp_region::ws_args.

Referenced by expand_omp(), and expand_omp_synch().

◆ expand_parallel_call()

static void expand_parallel_call ( struct omp_region * region,
basic_block bb,
gomp_parallel * entry_stmt,
vec< tree, va_gc > * ws_args )
static
Build the function calls to GOMP_parallel etc to actually
generate the parallel operation.  REGION is the parallel region
being expanded.  BB is the block where to insert the code.  WS_ARGS
will be set if this is a call to a combined parallel+workshare
construct, it contains the list of additional arguments needed by
the workshare construct.   

References add_bb_to_loop(), add_phi_arg(), build2(), build_call_expr_loc_vec(), build_fold_addr_expr, build_int_cst(), builtin_decl_explicit(), CDI_DOMINATORS, cfun, create_empty_bb(), create_phi_node(), create_tmp_var, expand_omp_build_assign(), fold_build2_loc(), fold_convert, fold_convert_loc(), force_gimple_operand_gsi(), gcc_assert, gcc_unreachable, ggc_alloc(), gimple_boolify(), gimple_build_cond_empty(), gimple_in_ssa_p(), gimple_location(), gimple_omp_parallel_child_fn(), gimple_omp_parallel_clauses(), gimple_omp_parallel_data_arg(), GSI_CONTINUE_LINKING, gsi_insert_after(), gsi_last_nondebug_bb(), gsi_start_bb(), omp_region::has_lastprivate_conditional, omp_region::inner, integer_zerop(), is_combined_parallel(), make_edge(), make_ssa_name(), NULL, null_pointer_node, NULL_TREE, OMP_CLAUSE__REDUCTEMP_, OMP_CLAUSE_DECL, OMP_CLAUSE_IF, OMP_CLAUSE_IF_EXPR, OMP_CLAUSE_LOCATION, OMP_CLAUSE_NUM_THREADS, OMP_CLAUSE_NUM_THREADS_EXPR, OMP_CLAUSE_PROC_BIND, OMP_CLAUSE_PROC_BIND_KIND, OMP_CLAUSE_SCHEDULE_AUTO, OMP_CLAUSE_SCHEDULE_DYNAMIC, OMP_CLAUSE_SCHEDULE_GUIDED, OMP_CLAUSE_SCHEDULE_MONOTONIC, OMP_CLAUSE_SCHEDULE_NONMONOTONIC, OMP_CLAUSE_SCHEDULE_RUNTIME, omp_find_clause(), pointer_sized_int_node, remove_edge(), omp_region::sched_kind, omp_region::sched_modifiers, set_immediate_dominator(), split_block_after_labels(), TREE_TYPE, omp_region::type, UNKNOWN_LOCATION, unsigned_type_node, vec_alloc(), vec_safe_length(), and omp_region::ws_args.

Referenced by expand_omp_taskreg().

◆ expand_task_call()

static void expand_task_call ( struct omp_region * region,
basic_block bb,
gomp_task * entry_stmt )
static
Build the function call to GOMP_task to actually
generate the task operation.  BB is the block where to insert the code.   

References boolean_true_node, build_call_expr(), build_fold_addr_expr, build_fold_addr_expr_loc(), build_int_cst(), builtin_decl_explicit(), omp_region::entry, fold_build2_loc(), fold_build3_loc(), fold_convert, fold_convert_loc(), force_gimple_operand_gsi(), g, gcc_assert, GF_OMP_FOR_KIND_TASKLOOP, ggc_alloc(), gimple_boolify(), gimple_location(), gimple_omp_for_clauses(), gimple_omp_for_kind(), gimple_omp_task_arg_align(), gimple_omp_task_arg_size(), gimple_omp_task_child_fn(), gimple_omp_task_clauses(), gimple_omp_task_copy_fn(), gimple_omp_task_data_arg(), gimple_omp_task_taskloop_p(), GSI_CONTINUE_LINKING, gsi_last_nondebug_bb(), integer_type_node, integer_zero_node, last_nondebug_stmt(), long_integer_type_node, long_long_unsigned_type_node, NULL, null_pointer_node, NULL_TREE, OMP_CLAUSE__LOOPTEMP_, OMP_CLAUSE_CHAIN, OMP_CLAUSE_DECL, OMP_CLAUSE_DEPEND, OMP_CLAUSE_DETACH, OMP_CLAUSE_FINAL, OMP_CLAUSE_FINAL_EXPR, OMP_CLAUSE_GRAINSIZE, OMP_CLAUSE_GRAINSIZE_EXPR, OMP_CLAUSE_GRAINSIZE_STRICT, OMP_CLAUSE_IF, OMP_CLAUSE_IF_EXPR, OMP_CLAUSE_MERGEABLE, OMP_CLAUSE_NOGROUP, OMP_CLAUSE_NUM_TASKS, OMP_CLAUSE_NUM_TASKS_EXPR, OMP_CLAUSE_NUM_TASKS_STRICT, OMP_CLAUSE_PRIORITY, OMP_CLAUSE_PRIORITY_EXPR, OMP_CLAUSE_REDUCTION, OMP_CLAUSE_UNTIED, omp_extract_for_data(), omp_find_clause(), omp_region::outer, ptr_type_node, and unsigned_type_node.

Referenced by expand_omp_taskreg().

◆ expand_taskwait_call()

static void expand_taskwait_call ( basic_block bb,
gomp_task * entry_stmt )
static
Build the function call to GOMP_taskwait_depend to actually
generate the taskwait operation.  BB is the block where to insert the
code.   

References build_call_expr(), builtin_decl_explicit(), force_gimple_operand_gsi(), ggc_alloc(), gimple_omp_task_clauses(), GSI_CONTINUE_LINKING, gsi_last_nondebug_bb(), NULL_TREE, OMP_CLAUSE_DECL, OMP_CLAUSE_DEPEND, OMP_CLAUSE_NOWAIT, and omp_find_clause().

Referenced by expand_omp_taskreg().

◆ expand_teams_call()

◆ extract_omp_for_update_vars()

static basic_block extract_omp_for_update_vars ( struct omp_for_data * fd,
tree * nonrect_bounds,
basic_block cont_bb,
basic_block body_bb )
static
Helper function for expand_omp_for_*.  Generate code like:
 L10:
     V3 += STEP3;
     if (V3 cond3 N32) goto BODY_BB; else goto L11;
 L11:
     V3 = N31;
     V2 += STEP2;
     if (V2 cond2 N22) goto BODY_BB; else goto L12;
 L12:
     V2 = N21;
     V1 += STEP1;
     goto BODY_BB;
For non-rectangular loops, use temporaries stored in nonrect_bounds
for the upper bounds if M?2 multiplier is present.  Given e.g.
for (V1 = N11; V1 cond1 N12; V1 += STEP1)
for (V2 = N21; V2 cond2 N22; V2 += STEP2)
for (V3 = N31; V3 cond3 N32; V3 += STEP3)
for (V4 = N41 + M41 * V2; V4 cond4 N42 + M42 * V2; V4 += STEP4)
do:
 L10:
     V4 += STEP4;
     if (V4 cond4 NONRECT_BOUND4) goto BODY_BB; else goto L11;
 L11:
     V4 = N41 + M41 * V2; // This can be left out if the loop
                     // refers to the immediate parent loop
     V3 += STEP3;
     if (V3 cond3 N32) goto BODY_BB; else goto L12;
 L12:
     V3 = N31;
     V2 += STEP2;
     if (V2 cond2 N22) goto L120; else goto L13;
 L120:
     V4 = N41 + M41 * V2;
     NONRECT_BOUND4 = N42 + M42 * V2;
     if (V4 cond4 NONRECT_BOUND4) goto BODY_BB; else goto L12;
 L13:
     V2 = N21;
     V1 += STEP1;
     goto L120;   

References add_bb_to_loop(), profile_probability::apply_scale(), boolean_type_node, CDI_DOMINATORS, omp_for_data_loop::cond_code, create_empty_bb(), DECL_P, expand_omp_regimplify_p(), fold_build2, fold_build_pointer_plus, force_gimple_operand_gsi(), ggc_alloc(), gimple_build_assign(), gimple_build_cond(), gimple_build_cond_empty(), gimple_cond_lhs_ptr(), gimple_cond_rhs_ptr(), gimple_regimplify_operands(), GSI_CONTINUE_LINKING, gsi_insert_after(), gsi_start_bb(), profile_probability::guessed_always(), i, basic_block_def::loop_father, omp_for_data_loop::m1, omp_for_data_loop::m2, make_edge(), omp_for_data_loop::n1, omp_for_data_loop::n2, NULL, NULL_TREE, omp_for_data_loop::outer, POINTER_TYPE_P, set_immediate_dominator(), TREE_ADDRESSABLE, TREE_TYPE, unshare_expr(), omp_for_data_loop::v, and walk_tree.

Referenced by expand_omp_for_generic(), expand_omp_for_static_chunk(), expand_omp_for_static_nochunk(), and expand_omp_taskloop_for_inner().

◆ find_lastprivate_looptemp()

static tree find_lastprivate_looptemp ( struct omp_for_data * fd,
tree innerc )
static
Return the last _looptemp_ clause if one has been created for
lastprivate on distribute parallel for{, simd} or taskloop.
FD is the loop data and INNERC should be the second _looptemp_
clause (the one holding the end of the range).
This is followed by collapse - 1 _looptemp_ clauses for the
counts[1] and up, and for triangular loops followed by 4
further _looptemp_ clauses (one for counts[0], one first_inner_iterations,
one factor and one adjn1).  After this there is optionally one
_looptemp_ clause that this function returns.   

References count, gcc_assert, ggc_alloc(), i, OMP_CLAUSE__LOOPTEMP_, OMP_CLAUSE_CHAIN, omp_find_clause(), TREE_TYPE, and TYPE_UNSIGNED.

Referenced by expand_omp_for_static_chunk(), expand_omp_for_static_nochunk(), and expand_omp_taskloop_for_outer().

◆ find_phi_with_arg_on_edge()

static gphi * find_phi_with_arg_on_edge ( tree arg,
edge e )
static
Return phi in E->DEST with ARG on edge E.   

References ggc_alloc(), gsi_end_p(), gsi_next(), gsi_start_phis(), NULL, and PHI_ARG_DEF_FROM_EDGE.

Referenced by expand_omp_for_generic(), and expand_omp_for_static_chunk().

◆ free_omp_region_1()

static void free_omp_region_1 ( struct omp_region * region)
static
Release the memory associated with the region tree rooted at REGION.   

References free(), free_omp_region_1(), i, omp_region::inner, and omp_region::next.

Referenced by free_omp_region_1(), and omp_free_regions().

◆ get_target_argument_identifier()

static tree get_target_argument_identifier ( int device,
bool subseqent_param,
int id )
static
Like above but return it in type that can be directly stored as an element
of the argument array.   

References fold_convert, get_target_argument_identifier_1(), ggc_alloc(), and ptr_type_node.

Referenced by push_target_argument_according_to_value().

◆ get_target_argument_identifier_1()

static tree get_target_argument_identifier_1 ( int device,
bool subseqent_param,
int id )
static
Build target argument identifier from the DEVICE identifier, value
identifier ID and whether the element also has a SUBSEQUENT_PARAM.   

References build_int_cst(), fold_build2, ggc_alloc(), and integer_type_node.

Referenced by get_target_argument_identifier(), and get_target_argument_value().

◆ get_target_argument_value()

static tree get_target_argument_value ( gimple_stmt_iterator * gsi,
int device,
int id,
tree value )
static
Return a target argument consisting of DEVICE identifier, value identifier
ID, and the actual VALUE.   

References build_int_cst(), fold_build2, fold_convert, force_gimple_operand_gsi(), get_target_argument_identifier_1(), ggc_alloc(), GSI_SAME_STMT, integer_type_node, NULL, ptr_type_node, and unsigned_type_node.

Referenced by push_target_argument_according_to_value().

◆ get_target_arguments()

◆ get_ws_args_for()

◆ gimple_build_cond_empty()

◆ is_combined_parallel()

static bool is_combined_parallel ( struct omp_region * region)
inlinestatic
Return true if REGION is a combined parallel+workshare region.   

References omp_region::is_combined_parallel.

Referenced by expand_omp_for_generic(), expand_omp_sections(), expand_omp_taskreg(), and expand_parallel_call().

◆ make_pass_expand_omp()

gimple_opt_pass * make_pass_expand_omp ( gcc::context * ctxt)

References ggc_alloc().

◆ make_pass_expand_omp_ssa()

gimple_opt_pass * make_pass_expand_omp_ssa ( gcc::context * ctxt)

References ggc_alloc().

◆ mark_loops_in_oacc_kernels_region()

static void mark_loops_in_oacc_kernels_region ( basic_block region_entry,
basic_block region_exit )
static
Mark the loops inside the kernels region starting at REGION_ENTRY and ending
at REGION_EXIT.   

References CDI_DOMINATORS, dominated_by_p(), gcc_assert, ggc_alloc(), loop::header, loop::in_oacc_kernels_region, loop::inner, loop_outer(), loop::next, and NULL.

Referenced by expand_omp_target().

◆ new_omp_region()

static struct omp_region * new_omp_region ( basic_block bb,
enum gimple_code type,
struct omp_region * parent )
static
Create a new parallel region starting at STMT inside region PARENT.   

References omp_region::entry, ggc_alloc(), omp_region::inner, omp_region::next, omp_region::outer, root_omp_region, type(), and omp_region::type.

Referenced by build_omp_regions_1(), and omp_make_gimple_edges().

◆ omp_adjust_chunk_size()

static tree omp_adjust_chunk_size ( tree chunk_size,
bool simd_schedule )
static
Adjust CHUNK_SIZE from SCHEDULE clause, depending on simd modifier
presence (SIMD_SCHEDULE).   

References build_int_cst(), omp_for_data::chunk_size, fold_build2, ggc_alloc(), integer_zerop(), known_eq, omp_max_vf(), omp_for_data::simd_schedule, and TREE_TYPE.

Referenced by expand_omp_for_generic(), expand_omp_for_static_chunk(), and get_ws_args_for().

◆ omp_expand_local()

void omp_expand_local ( basic_block head)
Expands omp construct (and its subconstructs) starting in HEAD.   

References build_omp_regions_root(), dump_file, dump_flags, dump_omp_region(), expand_omp(), ggc_alloc(), omp_free_regions(), remove_exit_barriers(), root_omp_region, and TDF_DETAILS.

◆ omp_free_regions()

void omp_free_regions ( void )
Release the memory for the entire omp region tree.   

References free_omp_region_1(), omp_region::next, NULL, r, and root_omp_region.

Referenced by execute_expand_omp(), make_edges(), and omp_expand_local().

◆ omp_make_gimple_edges()

◆ omp_memory_order_to_fail_memmodel()

◆ omp_memory_order_to_memmodel()

◆ optimize_omp_library_calls()

static void optimize_omp_library_calls ( gimple * entry_stmt)
static
Optimize omp_get_thread_num () and omp_get_num_threads ()
calls.  These can't be declared as const functions, but
within one parallel body they are constant, so they can be
transformed there into __builtin_omp_get_{thread_num,num_threads} ()
which are declared const.  Similarly for task body, except
that in untied task omp_get_thread_num () can change at any task
scheduling point.   

References builtin_decl_explicit(), cfun, DECL_ASSEMBLER_NAME, DECL_EXTERNAL, DECL_INITIAL, DECL_NAME, FOR_EACH_BB_FN, ggc_alloc(), gimple_call_fndecl(), gimple_call_num_args(), gimple_call_set_fndecl(), gimple_omp_task_clauses(), gsi_end_p(), gsi_next(), gsi_start_bb(), gsi_stmt(), is_gimple_call(), NULL, OMP_CLAUSE_UNTIED, omp_find_clause(), TREE_CODE, TREE_NOTHROW, TREE_PUBLIC, TREE_TYPE, and types_compatible_p().

Referenced by expand_omp_taskreg().

◆ push_target_argument_according_to_value()

static void push_target_argument_according_to_value ( gimple_stmt_iterator * gsi,
int device,
int id,
tree value,
vec< tree > * args )
static
If VALUE is an integer constant greater than -2^15 and smaller than 2^15,
push one argument to ARGS with both the DEVICE, ID and VALUE embedded in it,
otherwise push an identifier (with DEVICE and ID) and the VALUE in two
arguments.   

References fold_convert, force_gimple_operand_gsi(), get_target_argument_identifier(), get_target_argument_value(), ggc_alloc(), GSI_SAME_STMT, NULL, ptr_type_node, tree_fits_shwi_p(), and tree_to_shwi().

Referenced by get_target_arguments().

◆ remove_exit_barrier()

static void remove_exit_barrier ( struct omp_region * region)
static
Remove barriers in REGION->EXIT's block.  Note that this is only
valid for GIMPLE_OMP_PARALLEL regions.  Since the end of a parallel region
is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
removed.   

References BLOCK_SUPERCONTEXT, BLOCK_VARS, DECL_CHAIN, DECL_STRUCT_FUNCTION, omp_region::entry, omp_region::exit, FOR_EACH_EDGE, FOR_EACH_LOCAL_DECL, gcc_assert, ggc_alloc(), gimple_block(), gimple_omp_parallel_child_fn(), gimple_omp_return_nowait_p(), gimple_omp_return_set_nowait(), gsi_end_p(), gsi_last_nondebug_bb(), gsi_prev_nondebug(), gsi_stmt(), last_nondebug_stmt(), basic_block_def::preds, TREE_ADDRESSABLE, and TREE_CODE.

Referenced by remove_exit_barriers().

◆ remove_exit_barriers()

◆ vec2chain()

static tree vec2chain ( vec< tree, va_gc > * v)
static
Chain all the DECLs in LIST by their TREE_CHAIN fields.   

References DECL_CHAIN, FOR_EACH_VEC_SAFE_ELT_REVERSE, ggc_alloc(), and NULL_TREE.

Referenced by expand_omp_target(), and expand_omp_taskreg().

◆ workshare_safe_to_combine_p()

static bool workshare_safe_to_combine_p ( basic_block ws_entry_bb)
static
Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
is the immediate dominator of PAR_ENTRY_BB, return true if there
are no data dependencies that would prevent expanding the parallel
directive at PAR_ENTRY_BB as a combined parallel+workshare region.

When expanding a combined parallel+workshare region, the call to
the child function may need additional arguments in the case of
GIMPLE_OMP_FOR regions.  In some cases, these arguments are
computed out of variables passed in from the parent to the child
via 'struct .omp_data_s'.  For instance:

     #pragma omp parallel for schedule (guided, i * 4)
     for (j ...)

Is lowered into:

     # BLOCK 2 (PAR_ENTRY_BB)
     .omp_data_o.i = i;
     #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)

     # BLOCK 3 (WS_ENTRY_BB)
     .omp_data_i = &.omp_data_o;
     D.1667 = .omp_data_i->i;
     D.1598 = D.1667 * 4;
     #pragma omp for schedule (guided, D.1598)

When we outline the parallel region, the call to the child function
'bar.omp_fn.0' will need the value D.1598 in its argument list, but
that value is computed *after* the call site.  So, in principle we
cannot do the transformation.

To see whether the code in WS_ENTRY_BB blocks the combined
parallel+workshare call, we collect all the variables used in the
GIMPLE_OMP_FOR header check whether they appear on the LHS of any
statement in WS_ENTRY_BB.  If so, then we cannot emit the combined
call.

FIXME.  If we had the SSA form built at this point, we could merely
hoist the code in block 3 into block 2 and be done with it.  But at
this point we don't have dataflow information and though we could
hack something up here, it is really not worth the aggravation.   

References gcc_assert, GF_OMP_FOR_KIND_FOR, ggc_alloc(), gimple_omp_for_kind(), is_gimple_min_invariant(), last_nondebug_stmt(), long_integer_type_node, NULL, omp_extract_for_data(), and TREE_CODE.

Referenced by determine_parallel_type().

Variable Documentation

◆ omp_any_child_fn_dumped

bool omp_any_child_fn_dumped
static

◆ root_omp_region