GCC Middle and Back End API Reference
omp-low.c File Reference

Data Structures

struct  omp_context
struct  omp_for_data_loop
struct  omp_for_data
struct  omp_taskcopy_context

Typedefs

typedef struct omp_context omp_context

Functions

static void scan_omp (gimple_seq *, omp_context *)
static tree scan_omp_1_op (tree *, int *, void *)
static tree scan_omp_op ()
static void lower_omp (gimple_seq *, omp_context *)
static tree lookup_decl_in_outer_ctx (tree, omp_context *)
static tree maybe_lookup_decl_in_outer_ctx (tree, omp_context *)
tree find_omp_clause ()
static bool is_parallel_ctx ()
static bool is_task_ctx ()
static bool is_taskreg_ctx ()
static bool is_combined_parallel ()
static void extract_omp_for_data (gimple for_stmt, struct omp_for_data *fd, struct omp_for_data_loop *loops)
static bool workshare_safe_to_combine_p ()
static vec< tree, va_gc > * get_ws_args_for ()
static void determine_parallel_type ()
static bool is_variable_sized ()
static bool is_reference ()
static tree lookup_decl ()
static tree maybe_lookup_decl ()
static tree lookup_field ()
static tree lookup_sfield ()
static tree maybe_lookup_field ()
static bool use_pointer_for_field ()
tree copy_var_decl ()
static tree omp_copy_decl_2 ()
static tree omp_copy_decl_1 ()
static tree omp_build_component_ref ()
static tree build_receiver_ref ()
static tree build_outer_var_ref ()
static tree build_sender_ref ()
static void install_var_field ()
static tree install_var_local ()
static void fixup_remapped_decl ()
static tree omp_copy_decl ()
void dump_omp_region (FILE *, struct omp_region *, int)
void debug_omp_region (struct omp_region *)
void debug_all_omp_regions (void)
void dump_omp_region ()
DEBUG_FUNCTION void debug_omp_region ()
struct omp_regionnew_omp_region (basic_block bb, enum gimple_code type, struct omp_region *parent)
static void free_omp_region_1 ()
void free_omp_regions ()
static omp_contextnew_omp_context ()
static gimple_seq maybe_catch_exception (gimple_seq)
static void finalize_task_copyfn ()
static void delete_omp_context ()
static void fixup_child_record_type ()
static void scan_sharing_clauses ()
static tree create_omp_child_function_name ()
static void create_omp_child_function ()
static void scan_omp_parallel ()
static void scan_omp_task ()
static void scan_omp_for ()
static void scan_omp_sections ()
static void scan_omp_single ()
static bool check_omp_nesting_restrictions ()
static tree scan_omp_1_op ()
static tree scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p, struct walk_stmt_info *wi)
static void scan_omp ()
static tree build_omp_barrier ()
static omp_contextmaybe_lookup_ctx ()
static tree lookup_decl_in_outer_ctx ()
static tree maybe_lookup_decl_in_outer_ctx ()
tree omp_reduction_init ()
static int omp_max_vf ()
static bool lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf, tree &idx, tree &lane, tree &ivar, tree &lvar)
static void lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist, omp_context *ctx)
static void lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list, omp_context *ctx)
static void lower_reduction_clauses ()
static void lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist, omp_context *ctx)
static void lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
static void lower_send_shared_vars ()
static gimple gimple_build_cond_empty ()
static void expand_parallel_call (struct omp_region *region, basic_block bb, gimple entry_stmt, vec< tree, va_gc > *ws_args)
static void expand_task_call ()
static gimple_seq maybe_catch_exception ()
static tree vec2chain ()
static void remove_exit_barrier ()
static void remove_exit_barriers ()
static void optimize_omp_library_calls ()
static tree expand_omp_regimplify_p ()
static void expand_omp_build_assign ()
static void expand_omp_taskreg ()
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_iter_bb, int &first_zero_iter, basic_block &l2_dom_bb)
static void expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi, tree *counts, tree startvar)
static basic_block extract_omp_for_update_vars (struct omp_for_data *fd, basic_block cont_bb, basic_block body_bb)
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)
static void expand_omp_for_static_nochunk (struct omp_region *region, struct omp_for_data *fd)
static void expand_omp_for_static_chunk ()
static void expand_omp_simd ()
static void expand_omp_for ()
static void expand_omp_sections ()
static void expand_omp_single ()
static void expand_omp_synch ()
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_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 ()
static void expand_omp ()
static void build_omp_regions_1 (basic_block bb, struct omp_region *parent, bool single_tree)
static void build_omp_regions_root ()
void omp_expand_local ()
static void build_omp_regions ()
static unsigned int execute_expand_omp ()
static bool gate_expand_omp ()
gimple_opt_passmake_pass_expand_omp ()
static void lower_omp_sections ()
static void lower_omp_single_simple ()
static void lower_omp_single_copy ()
static void lower_omp_single ()
static void lower_omp_master ()
static void lower_omp_ordered ()
static void lower_omp_critical ()
static void lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p, gimple_seq *dlist, struct omp_context *ctx)
static void lower_omp_for ()
static tree check_combined_parallel (gimple_stmt_iterator *gsi_p, bool *handled_ops_p, struct walk_stmt_info *wi)
static tree task_copyfn_copy_decl ()
static tree task_copyfn_remap_type ()
static void create_task_copyfn ()
static void lower_omp_taskreg ()
static tree lower_omp_regimplify_p (tree *tp, int *walk_subtrees, void *data)
static void lower_omp_1 ()
static void lower_omp ()
static unsigned int execute_lower_omp ()
gimple_opt_passmake_pass_lower_omp ()
static bool diagnose_sb_0 (gimple_stmt_iterator *gsi_p, gimple branch_ctx, gimple label_ctx)
static tree diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p, struct walk_stmt_info *wi)
static tree diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p, struct walk_stmt_info *wi)
static unsigned int diagnose_omp_structured_block_errors ()
static bool gate_diagnose_omp_blocks ()
gimple_opt_passmake_pass_diagnose_omp_blocks ()

Variables

static splay_tree all_contexts
static int taskreg_nesting_level
struct omp_regionroot_omp_region
static bitmap task_shared_vars
static unsigned int tmp_ompfn_id_num
static splay_tree critical_name_mutexes
static splay_tree all_labels

Typedef Documentation

typedef struct omp_context omp_context
@verbatim Lowering pass for OpenMP directives.  Converts OpenMP directives

into explicit calls to the runtime library (libgomp) and data marshalling to implement data sharing and copying clauses. Contributed by Diego Novillo dnovi.nosp@m.llo@.nosp@m.redha.nosp@m.t.co.nosp@m.m

Copyright (C) 2005-2013 Free Software Foundation, Inc.

This file is part of GCC.

GCC is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version.

GCC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with GCC; see the file COPYING3. If not see http://www.gnu.org/licenses/.

Lowering of OpenMP parallel and workshare constructs proceeds in two
   phases.  The first phase scans the function looking for OMP statements
   and then for variables that must be replaced to satisfy data sharing
   clauses.  The second phase expands code for the constructs, as well as
   re-gimplifying things when variables have been replaced with complex
   expressions.

   Final code generation is done by pass_expand_omp.  The flowgraph is
   scanned for parallel regions which are then moved to a new
   function, to be invoked by the thread library.   
Context structure.  Used to store information about each parallel
   directive in the code.   

Function Documentation

static tree build_omp_barrier ( )
static
Re-gimplification and code generation routines.   
Build a call to GOMP_barrier.   

References build_call_expr(), and builtin_decl_explicit().

Referenced by expand_omp_for_static_chunk(), expand_omp_for_static_nochunk(), expand_omp_single(), and lower_rec_input_clauses().

static void build_omp_regions ( )
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(), and CDI_DOMINATORS.

Referenced by execute_expand_omp().

static void build_omp_regions_1 ( basic_block  bb,
struct omp_region parent,
bool  single_tree 
)
static
Helper for build_omp_regions.  Scan the dominator tree starting at
   block BB.  PARENT is the region that contains BB.  If SINGLE_TREE is
   true, the function ends once a single tree is built (otherwise, whole
   forest of OMP constructs may be built).   

References CDI_DOMINATORS, omp_region::cont, omp_region::exit, first_dom_son(), gsi_end_p(), gsi_last_bb(), gsi_stmt(), is_gimple_omp(), new_omp_region(), next_dom_son(), omp_region::outer, and omp_region::type.

Referenced by build_omp_regions(), and build_omp_regions_root().

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

References build_omp_regions_1().

Referenced by omp_expand_local().

static tree build_outer_var_ref ( )
static
Build tree nodes to access VAR in the scope outer to CTX.  In the case
   of a parallel, this is a component reference; for workshare constructs
   this is some variable.   

References build_receiver_ref(), GF_OMP_FOR_KIND_SIMD, gimple_omp_for_kind(), is_global_var(), is_reference(), is_taskreg_ctx(), is_variable_sized(), lookup_decl(), maybe_lookup_decl(), maybe_lookup_decl_in_outer_ctx(), omp_context::outer, omp_context::stmt, and use_pointer_for_field().

Referenced by lower_lastprivate_clauses(), lower_rec_input_clauses(), and lower_reduction_clauses().

static tree build_receiver_ref ( )
static
Build tree nodes to access the field for VAR on the receiver side.   

References lookup_field(), maybe_lookup_field(), omp_build_component_ref(), and omp_context::receiver_decl.

Referenced by build_outer_var_ref(), lower_copyprivate_clauses(), and lower_rec_input_clauses().

static tree build_sender_ref ( )
static
Build tree nodes to access the field for VAR on the sender side.   

References lookup_sfield(), omp_build_component_ref(), and omp_context::sender_decl.

Referenced by lower_copyprivate_clauses(), lower_send_clauses(), and lower_send_shared_vars().

static tree check_combined_parallel ( gimple_stmt_iterator gsi_p,
bool *  handled_ops_p,
struct walk_stmt_info wi 
)
static
Callback for walk_stmts.  Check if the current statement only contains
   GIMPLE_OMP_FOR or GIMPLE_OMP_PARALLEL.   

References gsi_stmt(), and walk_stmt_info::info.

Referenced by lower_omp_taskreg().

tree copy_var_decl ( )
Create a new VAR_DECL and copy information from VAR to it.   

References copy().

Referenced by omp_copy_decl_2(), and replace_by_duplicate_decl().

static tree create_omp_child_function_name ( )
static
DEBUG_FUNCTION void debug_all_omp_regions ( void  )

References dump_omp_region().

void debug_omp_region ( struct omp_region )
DEBUG_FUNCTION void debug_omp_region ( )

References dump_omp_region().

static void delete_omp_context ( )
static
static bool diagnose_sb_0 ( gimple_stmt_iterator gsi_p,
gimple  branch_ctx,
gimple  label_ctx 
)
static
Check for mismatched contexts and generate an error if needed.  Return
   true if an error is detected.   

References error(), gimple_build_nop(), and gsi_replace().

Referenced by diagnose_sb_2().

static tree diagnose_sb_1 ( gimple_stmt_iterator gsi_p,
bool *  handled_ops_p,
struct walk_stmt_info wi 
)
static
Pass 1: Create a minimal tree of OpenMP structured blocks, and record
   where each label is found.   

References gimple_label_label(), gimple_omp_body(), gimple_omp_for_pre_body(), gsi_stmt(), walk_stmt_info::info, and walk_gimple_seq().

Referenced by diagnose_omp_structured_block_errors().

static tree diagnose_sb_2 ( gimple_stmt_iterator gsi_p,
bool *  handled_ops_p,
struct walk_stmt_info wi 
)
static
void dump_omp_region ( FILE *  ,
struct omp_region ,
int   
)
Return the parallel region associated with STMT.   
Debugging dumps for parallel regions.   

Referenced by debug_all_omp_regions(), debug_omp_region(), dump_omp_region(), execute_expand_omp(), and omp_expand_local().

void dump_omp_region ( )
static unsigned int execute_expand_omp ( )
static
Main entry point for expanding OMP-GIMPLE into runtime calls.   

References build_omp_regions(), cleanup_tree_cfg(), dump_file, dump_omp_region(), expand_omp(), free_omp_regions(), and remove_exit_barriers().

static void expand_omp ( )
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 determine_parallel_type(), omp_region::entry, expand_omp_atomic(), expand_omp_for(), expand_omp_sections(), expand_omp_single(), expand_omp_synch(), expand_omp_taskreg(), gimple_has_location(), gimple_location(), omp_region::inner, input_location, last_stmt(), omp_region::next, and omp_region::type.

Referenced by execute_expand_omp(), and omp_expand_local().

static void expand_omp_atomic ( )
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 omp_region::entry, exact_log2(), omp_region::exit, expand_omp_atomic_fetch_op(), expand_omp_atomic_load(), expand_omp_atomic_mutex(), expand_omp_atomic_pipeline(), expand_omp_atomic_store(), first_stmt(), gimple_omp_atomic_load_lhs(), gimple_omp_atomic_load_rhs(), gimple_omp_atomic_store_val(), HOST_WIDE_INT, last_stmt(), single_succ(), and tree_low_cst().

Referenced by expand_omp().

static bool expand_omp_atomic_fetch_op ( basic_block  load_bb,
tree  addr,
tree  loaded_val,
tree  stored_val,
int  index 
)
static
A subroutine of expand_omp_atomic.  Attempt to implement the atomic
   operation as a __atomic_fetch_op builtin.  INDEX is log2 of the
   size of the data type, and thus usable to find the index of the builtin
   decl.  Returns false if the expression is not of the proper form.   

References build_call_expr_loc(), build_int_cst(), builtin_decl_explicit(), can_compare_and_swap_p(), cfun, commutative_tree_code(), fold_convert_loc(), force_gimple_operand_gsi(), gimple_assign_lhs(), gimple_assign_rhs1(), gimple_assign_rhs2(), gimple_assign_rhs_code(), gimple_in_ssa_p(), gimple_location(), gimple_omp_atomic_need_value_p(), gsi_after_labels(), gsi_last_bb(), gsi_next(), gsi_remove(), GSI_SAME_STMT, gsi_stmt(), is_gimple_assign(), last_stmt(), MEMMODEL_RELAXED, operand_equal_p(), single_succ(), and update_ssa().

Referenced by expand_omp_atomic().

static bool expand_omp_atomic_load ( basic_block  load_bb,
tree  addr,
tree  loaded_val,
int  index 
)
static
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(), builtin_decl_explicit(), cfun, force_gimple_operand_gsi(), gimple_in_ssa_p(), gsi_insert_before(), gsi_last_bb(), gsi_remove(), GSI_SAME_STMT, gsi_stmt(), si, unshare_expr(), and update_ssa().

Referenced by expand_omp_atomic().

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(), build_call_expr(), build_int_cst(), build_pointer_type_for_mode(), builtin_decl_explicit(), can_compare_and_swap_p(), cfun, create_phi_node(), create_tmp_reg(), create_tmp_var(), edge_def::flags, force_gimple_operand_gsi(), gimple_build_cond_empty(), gimple_in_ssa_p(), gimple_seq_empty_p(), gimple_seq_first_stmt(), gsi_insert_before(), gsi_last_bb(), gsi_remove(), GSI_SAME_STMT, gsi_start_bb(), gsi_stmt(), loop::header, loop::latch, basic_block_def::loop_father, make_edge(), make_ssa_name(), phi_nodes(), ptr_mode, si, single_succ(), single_succ_edge(), type(), and update_ssa().

Referenced by expand_omp_atomic().

static bool expand_omp_atomic_store ( basic_block  load_bb,
tree  addr,
tree  loaded_val,
tree  stored_val,
int  index 
)
static
static void expand_omp_build_assign ( )
static
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 
)
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.

    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 add_bb_to_loop(), add_loop(), alloc_loop(), build_call_expr(), build_int_cst(), builtin_decl_explicit(), CDI_DOMINATORS, omp_for_data::chunk_size, omp_for_data::collapse, omp_for_data_loop::cond_code, omp_region::cont, create_empty_bb(), create_tmp_var(), edge_def::dest, omp_region::entry, omp_region::exit, expand_omp_for_init_counts(), expand_omp_for_init_vars(), extract_omp_for_update_vars(), find_edge(), edge_def::flags, force_gimple_operand_gsi(), get_immediate_dominator(), gimple_build_call(), gimple_build_cond_empty(), gimple_omp_continue_control_def(), gimple_omp_continue_control_use(), gimple_omp_return_nowait_p(), GSI_CONTINUE_LINKING, gsi_end_p(), gsi_insert_after(), gsi_insert_before(), gsi_last_bb(), gsi_next(), gsi_prev(), gsi_remove(), GSI_SAME_STMT, gsi_start_bb(), gsi_stmt(), loop::header, is_combined_parallel(), omp_for_data::iter_type, loop::latch, omp_for_data::loop, basic_block_def::loop_father, make_edge(), omp_for_data_loop::n1, omp_for_data_loop::n2, phi_nodes(), phis, edge_def::probability, recompute_dominator(), remove_edge(), set_immediate_dominator(), signed_type_for(), single_succ(), split_block(), split_edge(), omp_for_data_loop::step, basic_block_def::succs, tree_int_cst_sgn(), type(), and omp_for_data_loop::v.

Referenced by expand_omp_for().

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_iter_bb,
int &  first_zero_iter,
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.   
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(), build_int_cst(), build_zero_cst(), CDI_DOMINATORS, cfun, omp_for_data::collapse, omp_for_data_loop::cond_code, create_empty_bb(), create_tmp_reg(), edge_def::dest, expand_omp_build_assign(), expand_omp_regimplify_p(), edge_def::flags, force_gimple_operand_gsi(), gimple_build_cond(), gimple_cond_lhs_ptr(), gimple_cond_rhs_ptr(), gimple_in_ssa_p(), gimple_regimplify_operands(), gsi_after_labels(), gsi_for_stmt(), gsi_insert_before(), gsi_last_bb(), GSI_SAME_STMT, integer_onep(), omp_for_data::loop, basic_block_def::loop_father, omp_for_data::loops, make_edge(), omp_for_data_loop::n1, omp_for_data_loop::n2, edge_def::probability, set_immediate_dominator(), signed_type_for(), split_block(), omp_for_data_loop::step, unshare_expr(), and omp_for_data_loop::v.

Referenced by expand_omp_for_generic(), and expand_omp_simd().

static void expand_omp_for_init_vars ( struct omp_for_data fd,
gimple_stmt_iterator gsi,
tree counts,
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.   

References omp_for_data::collapse, create_tmp_reg(), force_gimple_operand_gsi(), GSI_CONTINUE_LINKING, gsi_insert_after(), omp_for_data::loop, omp_for_data::loops, omp_for_data_loop::n1, signed_type_for(), omp_for_data_loop::step, and omp_for_data_loop::v.

Referenced by expand_omp_for_generic().

static void expand_omp_for_static_chunk ( )
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 add_loop(), add_phi_arg(), alloc_loop(), build_call_expr(), build_int_cst(), build_omp_barrier(), builtin_decl_explicit(), CDI_DOMINATORS, cfun, omp_for_data::chunk_size, omp_for_data_loop::cond_code, omp_region::cont, create_phi_node(), create_tmp_reg(), edge_def::dest, edge_def::dest_idx, omp_region::entry, omp_region::exit, expand_omp_regimplify_p(), find_edge(), edge_def::flags, force_gimple_operand_gsi(), gimple_build_cond(), gimple_build_cond_empty(), gimple_cond_lhs_ptr(), gimple_cond_rhs_ptr(), gimple_in_ssa_p(), gimple_omp_continue_control_def(), gimple_omp_continue_control_use(), gimple_omp_return_nowait_p(), gimple_phi_arg_def(), gimple_phi_arg_location_from_edge(), gimple_phi_result(), gimple_regimplify_operands(), GSI_CONTINUE_LINKING, gsi_end_p(), gsi_for_stmt(), gsi_insert_after(), gsi_insert_before(), gsi_last_bb(), gsi_next(), gsi_remove(), GSI_SAME_STMT, gsi_start_bb(), gsi_start_phis(), gsi_stmt(), loop::header, integer_onep(), last_stmt(), loop::latch, omp_for_data::loop, basic_block_def::loop_father, make_edge(), make_ssa_name(), omp_for_data_loop::n1, omp_for_data_loop::n2, edge_def::probability, 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(), remove_phi_node(), set_immediate_dominator(), si, signed_type_for(), single_pred_edge(), single_succ(), single_succ_edge(), split_block(), split_edge(), edge_def::src, omp_for_data_loop::step, basic_block_def::succs, type(), unshare_expr(), and omp_for_data_loop::v.

Referenced by expand_omp_for().

static void expand_omp_for_static_nochunk ( struct omp_region region,
struct omp_for_data fd 
)
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 add_loop(), add_phi_arg(), alloc_loop(), build_call_expr(), build_int_cst(), build_omp_barrier(), builtin_decl_explicit(), CDI_DOMINATORS, cfun, omp_for_data_loop::cond_code, omp_region::cont, create_tmp_reg(), edge_def::dest, edge_def::dest_idx, omp_region::entry, omp_region::exit, expand_omp_regimplify_p(), find_edge(), edge_def::flags, force_gimple_operand_gsi(), gimple_build_assign_with_ops(), gimple_build_cond(), gimple_build_cond_empty(), gimple_cond_lhs_ptr(), gimple_cond_rhs_ptr(), gimple_in_ssa_p(), gimple_omp_continue_control_def(), gimple_omp_continue_control_use(), gimple_omp_return_nowait_p(), gimple_phi_arg_def(), gimple_regimplify_operands(), GSI_CONTINUE_LINKING, gsi_end_p(), gsi_for_stmt(), gsi_insert_after(), gsi_insert_before(), gsi_last_bb(), gsi_next(), gsi_remove(), GSI_SAME_STMT, gsi_start_bb(), gsi_start_phis(), gsi_stmt(), loop::header, integer_onep(), loop::latch, omp_for_data::loop, basic_block_def::loop_father, make_edge(), omp_for_data_loop::n1, omp_for_data_loop::n2, edge_def::probability, recompute_dominator(), set_immediate_dominator(), signed_type_for(), single_succ(), split_block(), split_edge(), omp_for_data_loop::step, basic_block_def::succs, type(), unshare_expr(), and omp_for_data_loop::v.

Referenced by expand_omp_for().

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

References recompute_tree_invariant_for_addr_expr().

Referenced by expand_omp_build_assign(), expand_omp_for_init_counts(), expand_omp_for_static_chunk(), expand_omp_for_static_nochunk(), and expand_omp_simd().

static void expand_omp_sections ( )
static
static void expand_omp_simd ( )
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, 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 (cond3 is <)
          adj = STEP3 - 1;
        else
          adj = STEP3 + 1;
        count3 = (adj + N32 - N31) / STEP3;
        if (cond2 is <)
          adj = STEP2 - 1;
        else
          adj = STEP2 + 1;
        count2 = (adj + N22 - N21) / STEP2;
        if (cond1 is <)
          adj = STEP1 - 1;
        else
          adj = STEP1 + 1;
        count1 = (adj + N12 - N11) / STEP1;
        count = count1 * count2 * count3;
        V = 0;
        V1 = N11;
        V2 = N21;
        V3 = N31;
        goto L1;
    L0:
        BODY;
        V += 1;
        V3 += STEP3;
        V2 += (V3 cond3 N32) ? 0 : STEP2;
        V3 = (V3 cond3 N32) ? V3 : N31;
        V1 += (V2 cond2 N22) ? 0 : STEP1;
        V2 = (V2 cond2 N22) ? V2 : N21;
    L1:
        if (V < count) goto L0; else goto L2;
    L2:

References add_loop(), alloc_loop(), build_int_cst(), CDI_DOMINATORS, cfun, omp_for_data::collapse, omp_for_data_loop::cond_code, omp_region::cont, edge_def::dest, omp_region::entry, omp_region::exit, expand_omp_build_assign(), expand_omp_for_init_counts(), expand_omp_regimplify_p(), find_omp_clause(), edge_def::flags, basic_block_def::flags, omp_for_data::for_stmt, force_gimple_operand_gsi(), loop::force_vect, gimple_build_cond_empty(), gimple_cond_lhs_ptr(), gimple_cond_rhs_ptr(), gimple_in_ssa_p(), gimple_omp_for_clauses(), gimple_regimplify_operands(), GSI_CONTINUE_LINKING, gsi_for_stmt(), gsi_insert_after(), gsi_last_bb(), gsi_remove(), gsi_start_bb(), gsi_stmt(), function::has_force_vect_loops, function::has_simduid_loops, loop::header, host_integerp(), HOST_WIDE_INT, last_stmt(), loop::latch, omp_for_data::loop, basic_block_def::loop_father, omp_for_data::loops, make_edge(), omp_for_data_loop::n1, omp_for_data_loop::n2, OMP_CLAUSE__SIMDUID_, OMP_CLAUSE_SAFELEN, edge_def::probability, remove_edge(), loop::safelen, set_immediate_dominator(), signed_type_for(), loop::simduid, single_succ(), single_succ_edge(), split_block(), split_edge(), omp_for_data_loop::step, basic_block_def::succs, tree_low_cst(), type(), and omp_for_data_loop::v.

Referenced by expand_omp_for().

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

References build_omp_barrier(), omp_region::entry, omp_region::exit, find_omp_clause(), edge_def::flags, force_gimple_operand_gsi(), gimple_omp_return_nowait_p(), gimple_omp_single_clauses(), gsi_last_bb(), gsi_remove(), GSI_SAME_STMT, gsi_stmt(), OMP_CLAUSE_COPYPRIVATE, si, and single_succ_edge().

Referenced by expand_omp().

static void expand_omp_synch ( )
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, edge_def::flags, gsi_last_bb(), gsi_remove(), gsi_stmt(), si, and single_succ_edge().

Referenced by expand_omp().

static basic_block extract_omp_for_update_vars ( struct omp_for_data fd,
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;   

References add_bb_to_loop(), CDI_DOMINATORS, omp_for_data::collapse, omp_for_data_loop::cond_code, create_empty_bb(), force_gimple_operand_gsi(), gimple_build_cond_empty(), GSI_CONTINUE_LINKING, gsi_insert_after(), gsi_start_bb(), last_bb, basic_block_def::loop_father, omp_for_data::loops, make_edge(), omp_for_data_loop::n1, omp_for_data_loop::n2, edge_def::probability, set_immediate_dominator(), omp_for_data_loop::step, and omp_for_data_loop::v.

Referenced by expand_omp_for_generic().

static void fixup_remapped_decl ( )
static
Adjust the replacement for DECL in CTX for the new context.  This means
   copying the DECL_VALUE_EXPR, and fixing up the type.   

References omp_context::cb, copy_tree_body_r(), lookup_decl(), remap_decl(), and remap_type().

Referenced by scan_sharing_clauses().

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

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

Referenced by free_omp_regions().

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

References free_omp_region_1(), and omp_region::next.

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

static bool gate_diagnose_omp_blocks ( )
static
static bool gate_expand_omp ( )
static
OMP expansion -- the default pass, run before creation of SSA form.   

References seen_error().

static vec<tree, va_gc>* get_ws_args_for ( )
static
Collect additional arguments needed to emit a combined
   parallel+workshare call.  WS_STMT is the workshare directive being
   expanded.   

References build_int_cst(), omp_for_data::chunk_size, extract_omp_for_data(), fold_convert_loc(), gimple_location(), omp_for_data::loop, omp_for_data_loop::n1, omp_for_data_loop::n2, single_succ(), omp_for_data_loop::step, basic_block_def::succs, and vec_alloc().

Referenced by determine_parallel_type().

static gimple gimple_build_cond_empty ( )
static
static void install_var_field ( )
static
static tree install_var_local ( )
static
static bool is_combined_parallel ( )
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().

static bool is_parallel_ctx ( )
inlinestatic
Return true if CTX is for an omp parallel.   

References omp_context::stmt.

Referenced by lower_lastprivate_clauses().

static bool is_task_ctx ( )
inlinestatic
static bool is_taskreg_ctx ( )
inlinestatic
Return true if CTX is for an omp parallel or omp task.   

References omp_context::stmt.

Referenced by build_outer_var_ref(), omp_copy_decl(), scan_sharing_clauses(), and use_pointer_for_field().

static bool is_variable_sized ( )
inlinestatic
static tree lookup_decl ( )
inlinestatic
Lookup variables in the decl or field splay trees.  The "maybe" form
   allows for the variable form to not have been entered, otherwise we
   assert that the variable must have been entered.   

References omp_context::cb, copy_body_data::decl_map, and pointer_map_contains().

Referenced by build_outer_var_ref(), fixup_remapped_decl(), lower_lastprivate_clauses(), lower_rec_input_clauses(), and lower_reduction_clauses().

static tree lookup_decl_in_outer_ctx ( tree  ,
omp_context  
)
static
static tree lookup_decl_in_outer_ctx ( )
static
Find the mapping for DECL in CTX or the immediately enclosing
   context that has a mapping for DECL.

   If CTX is a nested parallel directive, we may have to use the decl
   mappings created in CTX's parent context.  Suppose that we have the
   following parallel nesting (variable UIDs showed for clarity):

        iD.1562 = 0;
        #omp parallel shared(iD.1562)           -> outer parallel
          iD.1562 = iD.1562 + 1;

          #omp parallel shared (iD.1562)        -> inner parallel
             iD.1562 = iD.1562 - 1;

   Each parallel structure will create a distinct .omp_data_s structure
   for copying iD.1562 in/out of the directive:

        outer parallel          .omp_data_s.1.i -> iD.1562
        inner parallel          .omp_data_s.2.i -> iD.1562

   A shared variable mapping will produce a copy-out operation before
   the parallel directive and a copy-in operation after it.  So, in
   this case we would have:

        iD.1562 = 0;
        .omp_data_o.1.i = iD.1562;
        #omp parallel shared(iD.1562)           -> outer parallel
          .omp_data_i.1 = &.omp_data_o.1
          .omp_data_i.1->i = .omp_data_i.1->i + 1;

          .omp_data_o.2.i = iD.1562;            -> **
          #omp parallel shared(iD.1562)         -> inner parallel
            .omp_data_i.2 = &.omp_data_o.2
            .omp_data_i.2->i = .omp_data_i.2->i - 1;


    ** This is a problem.  The symbol iD.1562 cannot be referenced
       inside the body of the outer parallel region.  But since we are
       emitting this copy operation while expanding the inner parallel
       directive, we need to access the CTX structure of the outer
       parallel directive to get the correct mapping:

          .omp_data_o.2.i = .omp_data_i.1->i

    Since there may be other workshare or parallel directives enclosing
    the parallel directive, it may be necessary to walk up the context
    parent chain.  This is not a problem in general because nested
    parallelism happens only rarely.   

References is_global_var(), omp_context::is_nested, maybe_lookup_decl(), and omp_context::outer.

static tree lookup_field ( )
inlinestatic

References omp_context::field_map.

Referenced by build_receiver_ref().

static tree lookup_sfield ( )
inlinestatic
static void lower_omp ( )
static
static void lower_omp_for_lastprivate ( struct omp_for_data fd,
gimple_seq body_p,
gimple_seq dlist,
struct omp_context ctx 
)
static
A subroutine of lower_omp_for.  Generate code to emit the predicate
   for a lastprivate clause.  Given a loop control predicate of (V
   cond N2), we gate the clause on (!(V cond N2)).  The lowered form
   is appended to *DLIST, iterator initialization is appended to
   *BODY_P.   

References build_int_cst(), omp_for_data_loop::cond_code, omp_for_data::for_stmt, gimple_omp_for_clauses(), gimple_seq_add_seq(), gimple_seq_empty_p(), gimplify_assign(), host_integerp(), HOST_WIDE_INT, integer_zerop(), omp_for_data::loop, lower_lastprivate_clauses(), omp_for_data_loop::n1, omp_for_data_loop::n2, omp_for_data_loop::step, unshare_expr(), and omp_for_data_loop::v.

Referenced by lower_omp_for().

static tree lower_omp_regimplify_p ( tree tp,
int *  walk_subtrees,
void *  data 
)
static
Callback for lower_omp_1.  Return non-NULL if *tp needs to be
   regimplified.  If DATA is non-NULL, lower_omp_1 is outside
   of OpenMP context, but with task_shared_vars set.   

References bitmap_bit_p(), and recompute_tree_invariant_for_addr_expr().

Referenced by lower_omp_1().

static void lower_omp_single_copy ( )
static
A subroutine of lower_omp_single.  Expand the simple form of
   a GIMPLE_OMP_SINGLE, with a copyprivate clause:

        #pragma omp single copyprivate (a, b, c)

   Create a new structure to hold copies of 'a', 'b' and 'c' and emit:

      {
        if ((copyout_p = GOMP_single_copy_start ()) == NULL)
          {
            BODY;
            copyout.a = a;
            copyout.b = b;
            copyout.c = c;
            GOMP_single_copy_end (&copyout);
          }
        else
          {
            a = copyout_p->a;
            b = copyout_p->b;
            c = copyout_p->c;
          }
        GOMP_barrier ();
      }

  FIXME.  It may be better to delay expanding the logic of this until
  pass_expand_omp.  The expanded logic may make the job more difficult
  to a synchronization analysis pass.   

References build_and_jump(), build_call_expr_loc(), build_fold_addr_expr_loc(), build_int_cst(), build_pointer_type(), builtin_decl_explicit(), create_artificial_label(), create_tmp_var(), fold_convert_loc(), gimple_build_label(), gimple_location(), gimple_omp_body(), gimple_omp_single_clauses(), gimple_seq_add_seq(), gimple_seq_add_stmt(), gimplify_and_add(), gimplify_assign(), lower_copyprivate_clauses(), omp_context::receiver_decl, omp_context::record_type, and omp_context::sender_decl.

Referenced by lower_omp_single().

static void lower_omp_single_simple ( )
static
A subroutine of lower_omp_single.  Expand the simple form of
   a GIMPLE_OMP_SINGLE, without a copyprivate clause:

        if (GOMP_single_start ())
          BODY;
        [ GOMP_barrier (); ]    -> unless 'nowait' is present.

  FIXME.  It may be better to delay expanding the logic of this until
  pass_expand_omp.  The expanded logic may make the job more difficult
  to a synchronization analysis pass.   

References builtin_decl_explicit(), create_artificial_label(), create_tmp_var(), fold_convert_loc(), gimple_build_call(), gimple_build_cond(), gimple_build_label(), gimple_call_set_lhs(), gimple_location(), gimple_omp_body(), gimple_seq_add_seq(), and gimple_seq_add_stmt().

Referenced by lower_omp_single().

static void lower_rec_input_clauses ( tree  clauses,
gimple_seq ilist,
gimple_seq dlist,
omp_context ctx 
)
static
Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
   from the receiver (aka child) side and initializers for REFERENCE_TYPE
   private variables.  Initialization statements go in ILIST, while calls
   to destructors go in DLIST.   

References append_to_statement_list(), build_call_expr(), build_call_expr_loc(), build_fold_addr_expr_loc(), build_int_cst(), build_omp_barrier(), build_omp_clause(), build_outer_var_ref(), build_receiver_ref(), build_simple_mem_ref_loc(), builtin_decl_explicit(), c_kind, compare_tree_int(), create_artificial_label(), create_tmp_var(), create_tmp_var_raw(), lang_hooks::decls, find_omp_clause(), fold_convert_loc(), g, GF_OMP_FOR_KIND_FOR, GF_OMP_FOR_KIND_SIMD, gimple_add_tmp_var(), gimple_build_assign_with_ops(), gimple_build_call(), gimple_build_call_internal(), gimple_build_cond(), gimple_build_goto(), gimple_build_label(), gimple_call_set_lhs(), gimple_omp_body_ptr(), gimple_omp_for_clauses(), gimple_omp_for_kind(), gimple_omp_for_set_clauses(), gimple_seq_add_seq(), gimple_seq_add_stmt(), gimplify_and_add(), gimplify_assign(), gimplify_stmt(), walk_stmt_info::gsi, gsi_insert_before_without_update(), GSI_SAME_STMT, gsi_start_1(), is_global_var(), is_reference(), is_task_ctx(), is_variable_sized(), lookup_decl(), lower_omp(), lower_rec_simd_input_clauses(), maybe_lookup_decl(), maybe_lookup_decl_in_outer_ctx(), OMP_CLAUSE__SIMDUID_, lang_hooks_for_decls::omp_clause_assign_op, lang_hooks_for_decls::omp_clause_copy_ctor, OMP_CLAUSE_COPYIN, lang_hooks_for_decls::omp_clause_default_ctor, lang_hooks_for_decls::omp_clause_dtor, OMP_CLAUSE_FIRSTPRIVATE, OMP_CLAUSE_LASTPRIVATE, OMP_CLAUSE_LINEAR, OMP_CLAUSE_PRIVATE, OMP_CLAUSE_REDUCTION, OMP_CLAUSE_SAFELEN, OMP_CLAUSE_SHARED, omp_reduction_init(), omp_context::stmt, unshare_expr(), and use_pointer_for_field().

Referenced by lower_omp_for(), lower_omp_sections(), lower_omp_single(), and lower_omp_taskreg().

static bool lower_rec_simd_input_clauses ( tree  new_var,
omp_context ctx,
int &  max_vf,
tree idx,
tree lane,
tree ivar,
tree lvar 
)
static
static void lower_send_clauses ( tree  clauses,
gimple_seq ilist,
gimple_seq olist,
omp_context ctx 
)
static
static void lower_send_shared_vars ( )
static
Generate code to implement SHARED from the sender (aka parent)
   side.  This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
   list things that got automatically shared.   

References build_sender_ref(), gimplify_assign(), lookup_decl_in_outer_ctx(), maybe_lookup_decl(), omp_context::record_type, record_type(), omp_context::srecord_type, and use_pointer_for_field().

Referenced by lower_omp_taskreg().

gimple_opt_pass* make_pass_diagnose_omp_blocks ( )
gimple_opt_pass* make_pass_expand_omp ( )
gimple_opt_pass* make_pass_lower_omp ( )
static gimple_seq maybe_catch_exception ( )
static
If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
   catch handler and return it.  This prevents programs from violating the
   structured block semantics with throws.   

References builtin_decl_explicit(), lang_hooks::eh_protect_cleanup_actions, g, gimple_build_eh_must_not_throw(), gimple_build_try(), gimple_seq_alloc_with_stmt(), and GIMPLE_TRY_CATCH.

static omp_context* maybe_lookup_ctx ( )
static
If a context was created for STMT when it was scanned, return it.   

References all_contexts.

Referenced by lower_omp_1(), and lower_omp_sections().

static tree maybe_lookup_decl_in_outer_ctx ( tree  ,
omp_context  
)
static
static tree maybe_lookup_decl_in_outer_ctx ( )
static
Similar to lookup_decl_in_outer_ctx, but return DECL if not found
   in outer contexts.   

References maybe_lookup_decl(), and omp_context::outer.

static tree maybe_lookup_field ( )
inlinestatic

References omp_context::field_map.

Referenced by build_receiver_ref().

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

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

Referenced by build_omp_regions_1(), and make_edges().

static tree omp_build_component_ref ( )
static
Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
   as appropriate.   

Referenced by build_receiver_ref(), build_sender_ref(), and create_task_copyfn().

static tree omp_copy_decl ( )
static
The callback for remap_decl.  Search all containing contexts for a
   mapping of the variable; this avoids having to duplicate the splay
   tree ahead of time.  We know a mapping doesn't already exist in the
   given context.  Create new mappings to implement default semantics.   

References omp_context::cb, create_artificial_label(), current_function_decl, decl_function_context(), insert_decl_map(), is_global_var(), is_taskreg_ctx(), maybe_lookup_decl(), omp_context::outer, and copy_body_data::src_fn.

Referenced by new_omp_context().

static tree omp_copy_decl_1 ( )
static

References omp_copy_decl_2().

Referenced by install_var_local().

static tree omp_copy_decl_2 ( )
static
Construct a new automatic decl similar to VAR.   

References omp_context::block_vars, copy(), copy_var_decl(), and current_function_decl.

Referenced by omp_copy_decl_1().

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

References build_omp_regions_root(), dump_file, dump_flags, dump_omp_region(), expand_omp(), free_omp_regions(), and remove_exit_barriers().

Referenced by gen_parallel_loop().

static int omp_max_vf ( )
static
Return maximum possible vectorization factor for the target.   

References floor_log2(), and targetm.

Referenced by lower_rec_simd_input_clauses().

tree omp_reduction_init ( )
Construct the initialization value for reduction CLAUSE.   

References build_real(), build_zero_cst(), fold_convert_loc(), real_arithmetic(), real_inf(), and real_maxval().

static void optimize_omp_library_calls ( )
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(), find_omp_clause(), gimple_call_fndecl(), gimple_call_num_args(), gimple_call_set_fndecl(), gimple_omp_task_clauses(), walk_stmt_info::gsi, gsi_end_p(), gsi_next(), gsi_start_bb(), gsi_stmt(), is_gimple_call(), OMP_CLAUSE_UNTIED, and types_compatible_p().

Referenced by expand_omp_taskreg().

static void remove_exit_barrier ( )
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 omp_region::entry, omp_region::exit, gimple_block(), gimple_omp_parallel_child_fn(), gimple_omp_return_nowait_p(), gimple_omp_return_set_nowait(), walk_stmt_info::gsi, gsi_end_p(), gsi_last_bb(), gsi_prev(), gsi_stmt(), last_stmt(), basic_block_def::preds, and edge_def::src.

Referenced by remove_exit_barriers().

static void remove_exit_barriers ( )
static
static void scan_omp ( )
static
Scan all the statements starting at the current statement.  CTX
   contains context information about the OpenMP directives and
   clauses found during the scan.   

References walk_stmt_info::info, input_location, memset(), scan_omp_1_op(), scan_omp_1_stmt(), walk_gimple_seq_mod(), and walk_stmt_info::want_locations.

static tree scan_omp_1_op ( tree ,
int *  ,
void *   
)
static

Referenced by scan_omp(), and scan_omp_op().

static tree scan_omp_1_op ( )
static
Helper function scan_omp.

   Callback for walk_tree or operators in walk_gimple_stmt used to
   scan for OpenMP directives in TP.   

References build_int_cst_wide(), omp_context::cb, walk_stmt_info::info, remap_decl(), and remap_type().

static tree scan_omp_op ( )
inlinestatic
Convenience function for calling scan_omp_1_op on tree operands.   

References walk_stmt_info::info, memset(), scan_omp_1_op(), and walk_stmt_info::want_locations.

Referenced by scan_omp_for(), and scan_sharing_clauses().

static void scan_omp_sections ( )
static
static tree task_copyfn_copy_decl ( )
static
static tree vec2chain ( )
static
Chain all the DECLs in LIST by their TREE_CHAIN fields.   

Referenced by expand_omp_taskreg().

static bool workshare_safe_to_combine_p ( )
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 omp_for_data::chunk_size, omp_for_data::collapse, extract_omp_for_data(), is_gimple_min_invariant(), omp_for_data::iter_type, last_stmt(), omp_for_data::loop, omp_for_data_loop::n1, omp_for_data_loop::n2, and omp_for_data_loop::step.

Referenced by determine_parallel_type().


Variable Documentation

splay_tree all_contexts
static
splay_tree all_labels
static
The following is a utility to diagnose OpenMP structured block violations.
   It is not part of the "omplower" pass, as that's invoked too late.  It
   should be invoked by the respective front ends after gimplification.   
splay_tree critical_name_mutexes
static
Gimplify a GIMPLE_OMP_CRITICAL statement.  This is a relatively simple
   substitution of a couple of function calls.  But in the NAMED case,
   requires that languages coordinate a symbol name.  It is therefore
   best put here in common code.   
struct omp_region* root_omp_region

Referenced by make_edges(), and new_omp_region().

bitmap task_shared_vars
static
int taskreg_nesting_level
static
unsigned int tmp_ompfn_id_num
static
Create a new name for omp child function.  Returns an identifier.