GCC Middle and Back End API Reference
|
Go to the source code of this file.
Macros | |
#define | PENDING_STMT(e) ((e)->insns.g) |
#define | label_to_block(t) (label_to_block_fn (cfun, t)) |
#define label_to_block | ( | t | ) | (label_to_block_fn (cfun, t)) |
#define PENDING_STMT | ( | e | ) | ((e)->insns.g) |
Data and Control Flow Analysis for Trees. Copyright (C) 2001-2013 Free Software Foundation, Inc. Contributed by Diego Novillo dnovi llo@ redha t.co m
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/. Location to track pending stmt for edge insertion.
Referenced by gsi_insert_on_edge_immediate(), and gsi_move_after().
void add_phi_args_after_copy | ( | basic_block * | region_copy, |
unsigned | n_region, | ||
edge | e_copy | ||
) |
Blocks in REGION_COPY array of length N_REGION were created by duplication of basic blocks. Add phi node arguments for edges going from these blocks. If E_COPY is not NULL, also add phi node arguments for its destination.
Referenced by tm_memopt_clear_visited().
void add_phi_args_after_copy_bb | ( | basic_block | ) |
void cleanup_dead_labels | ( | void | ) |
Cleanup redundant labels. This is a three-step process: 1) Find the leading label for each block. 2) Redirect all references to labels to the leading labels. 3) Cleanup all useless labels.
Find a suitable label for each block. We use the first user-defined label if there is one, or otherwise just the first label we see.
If we have not yet seen a label for the current block, remember this one and see if there are more labels.
If we did see a label for the current block already, but it is an artificially created label, replace it if the current label is a user defined label.
Now redirect all jumps/branches to the selected label. First do so for each block ending in a control statement.
Replace all destination labels.
We have to handle gotos until they're removed, and we don't remove them until after we've created the CFG edges.
Do the same for the exception region tree labels.
Finally, purge dead labels. All user-defined labels and labels that can be the target of non-local gotos and labels which have their address taken are preserved.
If the main label of the block is unused, we may still remove it.
References gimple_asm_label_op(), main_block_label(), and TREE_VALUE.
void clear_special_calls | ( | void | ) |
Clear flags set by notice_special_calls. Used by dead code removal to update the flags.
void debug | ( | struct loop & | ref | ) |
void debug | ( | struct loop * | ptr | ) |
void debug_cfg_stats | ( | void | ) |
Dump CFG statistics on stderr. Keep extern so that it's always linked in the final executable.
References cfg_stats, DECL_NONLOCAL, gimple_label_label(), and cfg_stats_d::num_merged_labels.
void debug_function | ( | tree | , |
int | |||
) |
void debug_loop | ( | struct loop * | , |
int | |||
) |
void debug_loop_num | ( | unsigned | , |
int | |||
) |
void debug_loops | ( | int | ) |
void debug_verbose | ( | struct loop & | ref | ) |
void debug_verbose | ( | struct loop * | ptr | ) |
void delete_tree_cfg_annotations | ( | void | ) |
Remove block annotations and other data structures.
void dump_cfg_stats | ( | FILE * | ) |
void dump_function_to_file | ( | tree | , |
FILE * | , | ||
int | |||
) |
void end_recording_case_labels | ( | void | ) |
Stop recording information mapping edges to case labels and remove any information we have recorded.
unsigned int execute_fixup_cfg | ( | void | ) |
IPA passes, compilation of earlier functions or inlining might have changed some properties, such as marked functions nothrow, pure, const or noreturn. Remove redundant edges and basic blocks, and create new ones if necessary.
This pass can't be executed as stand alone pass from pass manager, because in between inlining and this fixup the verify_flow_info would fail.
If we have a basic block with no successors that does not end with a control statement or a noreturn call end it with a call to __builtin_unreachable. This situation can occur when inlining a noreturn call that does in fact return.
We just processed all calls. Dump a textual representation of the flowgraph.
void extract_true_false_edges_from_block | ( | basic_block | b, |
edge * | true_edge, | ||
edge * | false_edge | ||
) |
Given a basic block B which ends with a conditional and has precisely two successors, determine which of the edges is taken if the conditional is true and which is taken if the conditional is false. Set TRUE_EDGE and FALSE_EDGE appropriately.
Referenced by associate_equivalences_with_edges(), check_forbidden_calls(), operand_equal_for_value_replacement(), and simple_mem_ref_in_stmt().
edge find_taken_edge | ( | basic_block | , |
tree | |||
) |
gimple first_stmt | ( | basic_block | ) |
void fold_cond_expr_cond | ( | void | ) |
Fold COND_EXPR_COND of each COND_EXPR.
void gather_blocks_in_sese_region | ( | basic_block | entry, |
basic_block | exit, | ||
vec< basic_block > * | bbs_p | ||
) |
Add all the blocks dominated by ENTRY to the array BBS_P. Stop adding blocks when the dominator traversal reaches EXIT. This function silently assumes that ENTRY strictly dominates EXIT.
Referenced by create_loads_and_stores_for_name(), and move_stmt_r().
tree gimple_block_label | ( | basic_block | ) |
void gimple_debug_bb | ( | basic_block | ) |
basic_block gimple_debug_bb_n | ( | int | ) |
void gimple_debug_cfg | ( | int | ) |
void gimple_dump_cfg | ( | FILE * | , |
int | |||
) |
bool gimple_duplicate_sese_region | ( | edge | entry, |
edge | exit, | ||
basic_block * | region, | ||
unsigned | n_region, | ||
basic_block * | region_copy, | ||
bool | update_dominance | ||
) |
Duplicates a REGION (set of N_REGION basic blocks) with just a single important exit edge EXIT. By important we mean that no SSA name defined inside region is live over the other exit edges of the region. All entry edges to the region must go to ENTRY->dest. The edge ENTRY is redirected to the duplicate of the region. Dominance and loop information is updated if UPDATE_DOMINANCE is true, but not the SSA web. If UPDATE_DOMINANCE is false then we assume that the caller will update the dominance information after calling this function. The new basic blocks are stored to REGION_COPY in the same order as they had in REGION, provided that REGION_COPY is not NULL. The function returns false if it is unable to copy the region, true otherwise.
Some sanity checking. Note that we do not check for all possible missuses of the functions. I.e. if you ask to copy something weird, it will work, but the state of structures probably will not be correct.
We do not handle subloops, i.e. all the blocks must belong to the same loop.
In case the function is used for loop header copying (which is the primary use), ensure that EXIT and its copy will be new latch and entry edges.
Record blocks outside the region that are dominated by something inside.
Fix up corner cases, to avoid division by zero or creation of negative frequencies.
Fix up corner cases, to avoid division by zero or creation of negative frequencies.
Redirect the entry and add the phi node arguments.
Concerning updating of dominators: We must recount dominators for entry block and its copy. Anything that is outside of the region, but was dominated by something inside needs recounting as well.
Add the other PHI node arguments.
bool gimple_duplicate_sese_tail | ( | edge | entry, |
edge | exit, | ||
basic_block * | region, | ||
unsigned | n_region, | ||
basic_block * | region_copy | ||
) |
Duplicates REGION consisting of N_REGION blocks. The new blocks are stored to REGION_COPY in the same order in that they appear in REGION, if REGION_COPY is not NULL. ENTRY is the entry to the region, EXIT an exit from it. The condition guarding EXIT is moved to ENTRY. Returns true if duplication succeeds, false otherwise.
For example,
some_code; if (cond) A; else B;
is transformed to
if (cond) { some_code; A; } else { some_code; B; }
Record blocks outside the region that are dominated by something inside.
Fix up corner cases, to avoid division by zero or creation of negative frequencies.
Fix up corner cases, to avoid division by zero or creation of negative frequencies.
Create the switch block, and put the exit condition to it.
Register the new edge from SWITCH_BB in loop exit lists.
Add the PHI node arguments.
Get rid of now superfluous conditions and associated edges (and phi node arguments).
The latch of ORIG_LOOP was copied, and so was the backedge to the original header. We redirect this backedge to EXIT_BB.
Anything that is outside of the region, but was dominated by something inside needs to update dominance info.
Update the SSA web.
Referenced by create_loop_fn().
bool gimple_purge_all_dead_abnormal_call_edges | ( | const_bitmap | ) |
bool gimple_purge_all_dead_eh_edges | ( | const_bitmap | ) |
bool gimple_purge_dead_abnormal_call_edges | ( | basic_block | ) |
bool gimple_purge_dead_eh_edges | ( | basic_block | ) |
tree gimplify_build1 | ( | gimple_stmt_iterator * | gsi, |
enum tree_code | code, | ||
tree | type, | ||
tree | a | ||
) |
Build a unary operation and gimplify it. Emit code before GSI. Return the gimple_val holding the result.
Referenced by expand_complex_libcall().
Build a binary operation and gimplify it. Emit code before GSI. Return the gimple_val holding the result.
Referenced by add_rshift(), and expand_complex_libcall().
tree gimplify_build3 | ( | gimple_stmt_iterator * | gsi, |
enum tree_code | code, | ||
tree | type, | ||
tree | a, | ||
tree | b, | ||
tree | c | ||
) |
Build a ternary operation and gimplify it. Emit code before GSI. Return the gimple_val holding the result.
References current_ir_type(), edge_def::dest, edge_def::edge_def_insns::g, edge_def::goto_locus, gt_pch_nx(), edge_def::insns, IR_GIMPLE, LOCATION_BLOCK, edge_def::edge_def_insns::r, and edge_def::src.
void group_case_labels | ( | void | ) |
Look for blocks ending in a multiway branch (a GIMPLE_SWITCH), and scan the sorted vector of cases. Combine the ones jumping to the same label.
References edge_def::flags, gcc_checking_assert, gimple_phi_arg_edge(), PHI_ARG_INDEX_FROM_USE, replace_exp(), SSA_NAME_OCCURS_IN_ABNORMAL_PHI, and virtual_operand_p().
void group_case_labels_stmt | ( | gimple | ) |
void init_empty_tree_cfg | ( | void | ) |
void init_empty_tree_cfg_for_function | ( | struct function * | ) |
basic_block label_to_block_fn | ( | struct function * | , |
tree | |||
) |
gimple last_and_only_stmt | ( | basic_block | ) |
gimple last_stmt | ( | basic_block | ) |
void make_abnormal_goto_edges | ( | basic_block | , |
bool | |||
) |
basic_block move_sese_region_to_fn | ( | struct function * | dest_cfun, |
basic_block | entry_bb, | ||
basic_block | exit_bb, | ||
tree | orig_block | ||
) |
Move a single-entry, single-exit region delimited by ENTRY_BB and EXIT_BB to function DEST_CFUN. The whole region is replaced by a single basic block in the original CFG and the new basic block is returned. DEST_CFUN must not have a CFG yet.
Note that the region need not be a pure SESE region. Blocks inside the region may contain calls to abort/exit. The only restriction is that ENTRY_BB should be the only entry point and it must dominate EXIT_BB.
Change TREE_BLOCK of all statements in ORIG_BLOCK to the new functions outermost BLOCK, move all subblocks of ORIG_BLOCK to the new function.
All local variables referenced in the region are assumed to be in the corresponding BLOCK_VARS and unexpanded variable lists associated with DEST_CFUN.
If ENTRY does not strictly dominate EXIT, this cannot be an SESE region.
Collect all the blocks in the region. Manually add ENTRY_BB because it won't be added by dfs_enumerate_from.
The blocks that used to be dominated by something in BBS will now be dominated by the new block.
Detach ENTRY_BB and EXIT_BB from CFUN->CFG. We need to remember the predecessor edges to ENTRY_BB and the successor edges to EXIT_BB so that we can re-attach them to the new basic block that will replace the region.
Switch context to the child function to initialize DEST_FN's CFG.
Initialize EH information for the new function.
Initialize an empty loop tree.
Move the outlined loop tree part.
If the SESE region contains some bbs ending with a noreturn call, those are considered to belong to the outermost loop in saved_cfun, rather than the entry_bb's loop_father.
Remove loop exits from the outlined region.
Adjust the number of blocks in the tree root of the outlined part.
Setup a mapping to be used by move_block_to_fn.
Move blocks from BBS into DEST_CFUN.
No need to update edge counts on the last block. It has already been updated earlier when we detached the region from the original CFG.
Loop sizes are no longer correct, fix them up.
Rewire BLOCK_SUBBLOCKS of orig_block.
Rewire the entry and exit blocks. The successor to the entry block turns into the successor of DEST_FN's ENTRY_BLOCK_PTR in the child function. Similarly, the predecessor of DEST_FN's EXIT_BLOCK_PTR turns into the predecessor of EXIT_BLOCK_PTR. We need to switch CFUN between DEST_CFUN and SAVED_CFUN so that the various CFG manipulation function get to the right CFG. FIXME, this is silly. The CFG ought to become a parameter to these helpers.
Back in the original function, the SESE region has disappeared, create a new basic block in its place.
References gimple_body(), gimple_seq_first_stmt(), gimple_seq_last_stmt(), and print_gimple_seq().
void notice_special_calls | ( | gimple | ) |
void print_loops | ( | FILE * | , |
int | |||
) |
void print_loops_bb | ( | FILE * | , |
basic_block | , | ||
int | , | ||
int | |||
) |
void remove_edge_and_dominated_blocks | ( | edge | ) |
basic_block single_noncomplex_succ | ( | basic_block | bb | ) |
void start_recording_case_labels | ( | void | ) |
Start recording information mapping edges to case labels.
void verify_gimple_in_cfg | ( | struct function * | ) |
void verify_gimple_in_seq | ( | gimple_seq | ) |