GCC Middle and Back End API Reference
gimple-ssa-split-paths.cc File Reference
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "backend.h"
#include "tree.h"
#include "gimple.h"
#include "tree-pass.h"
#include "tree-cfg.h"
#include "cfganal.h"
#include "cfgloop.h"
#include "gimple-iterator.h"
#include "tracer.h"
#include "predict.h"
#include "gimple-ssa.h"
#include "tree-phinodes.h"
#include "ssa-iterators.h"
#include "fold-const.h"
Include dependency graph for gimple-ssa-split-paths.cc:

Functions

static basic_block find_block_to_duplicate_for_splitting_paths (basic_block latch)
 
static unsigned int count_stmts_in_block (basic_block bb)
 
static bool poor_ifcvt_candidate_code (enum tree_code code)
 
static bool is_feasible_trace (basic_block bb)
 
static bool split_paths ()
 
static unsigned int execute_split_paths ()
 
static bool gate_split_paths ()
 
gimple_opt_passmake_pass_split_paths (gcc::context *ctxt)
 

Function Documentation

◆ count_stmts_in_block()

static unsigned int count_stmts_in_block ( basic_block bb)
static
Return the number of non-debug statements in a block.   

References gsi_end_p(), gsi_next(), gsi_start_bb(), gsi_stmt(), and is_gimple_debug().

Referenced by is_feasible_trace().

◆ execute_split_paths()

static unsigned int execute_split_paths ( )
static
Main entry point for splitting paths.  Returns TODO_cleanup_cfg if any
paths where split, otherwise return zero.   

References CDI_DOMINATORS, cfun, changed, free_dominance_info(), mark_dfs_back_edges(), n_basic_blocks_for_fn, NUM_FIXED_BLOCKS, split_paths(), and TODO_cleanup_cfg.

◆ find_block_to_duplicate_for_splitting_paths()

static basic_block find_block_to_duplicate_for_splitting_paths ( basic_block latch)
static
Support routines for Splitting Paths to loop backedges
   Copyright (C) 2015-2024 Free Software Foundation, Inc.
   Contributed by Ajit Kumar Agarwal <ajitkum@xilinx.com>.

 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/>.   
Given LATCH, the latch block in a loop, see if the shape of the
path reaching LATCH is suitable for being split by duplication.
If so, return the block that will be duplicated into its predecessor
paths.  Else return NULL.   

References CDI_DOMINATORS, EDGE_COMPLEX, EDGE_COUNT, EDGE_PRED, EDGE_SUCC, find_edge(), gcc_assert, get_immediate_dominator(), ggc_alloc(), gsi_last_nondebug_bb(), gsi_stmt(), ignore_bb_p(), last, NULL, basic_block_def::preds, single_pred_edge(), single_pred_p(), single_succ_p(), and basic_block_def::succs.

Referenced by split_paths().

◆ gate_split_paths()

static bool gate_split_paths ( )
static

References ggc_alloc().

◆ is_feasible_trace()

static bool is_feasible_trace ( basic_block bb)
static
Return TRUE if BB is a reasonable block to duplicate by examining
its size, false otherwise.  BB will always be a loop latch block.

Things to consider:

  We do not want to spoil if-conversion if at all possible.

  Most of the benefit seems to be from eliminating the unconditional
  jump rather than CSE/DCE opportunities.  So favor duplicating
  small latches.  A latch with just a conditional branch is ideal.

  CSE/DCE opportunties crop up when statements from the predecessors
  feed statements in the latch and allow statements in the latch to
  simplify.   

References CDI_DOMINATORS, count_stmts_in_block(), dominated_by_p(), dump_file, dump_flags, EDGE_COUNT, EDGE_PRED, FOR_EACH_IMM_USE_FAST, get_immediate_dominator(), ggc_alloc(), gimple_assign_lhs(), gimple_assign_rhs1(), gimple_assign_rhs_code(), gimple_bb(), gimple_cond_code(), gimple_cond_lhs(), gimple_cond_rhs(), gimple_op(), gimple_phi_arg_def(), gimple_phi_num_args(), gimple_phi_result(), gsi_end_p(), gsi_last_bb(), gsi_next(), gsi_start_phis(), gsi_stmt(), loop::header, i, basic_block_def::index, is_gimple_assign(), is_gimple_debug(), last_and_only_stmt(), basic_block_def::loop_father, operand_equal_p(), poor_ifcvt_candidate_code(), si, single_pred(), single_pred_p(), tcc_comparison, TDF_DETAILS, TREE_CODE, TREE_CODE_CLASS, USE_STMT, and virtual_operand_p().

Referenced by split_paths().

◆ make_pass_split_paths()

gimple_opt_pass * make_pass_split_paths ( gcc::context * ctxt)

References ggc_alloc().

◆ poor_ifcvt_candidate_code()

static bool poor_ifcvt_candidate_code ( enum tree_code code)
static
Return TRUE if CODE represents a tree code that is not likely to
be easily if-convertable because it likely expands into multiple
insns, FALSE otherwise.   

References ggc_alloc().

Referenced by is_feasible_trace().

◆ split_paths()

static bool split_paths ( )
static
If the immediate dominator of the latch of the loop is
block with conditional branch, then the loop latch  is
duplicated to its predecessors path preserving the SSA
semantics.

CFG before transformation.

           2
           |
           |
     +---->3
     |    / \
     |   /   \
     |  4     5
     |   \   /
     |    \ /
     |     6
     |    / \
     |   /   \
     |  8     7
     |  |     |
     ---+     E



 Block 8 is the latch.  We're going to make copies of block 6 (9 & 10)
 and wire things up so they look like this:

           2
           |
           |
     +---->3
     |    / \
     |   /   \
     |  4     5
     |  |     |
     |  |     |
     |  9    10
     |  |\   /|
     |  | \ / |
     |  |  7  |
     |  |  |  |
     |  |  E  |
     |  |     |
     |   \   /
     |    \ /
     +-----8


 Blocks 9 and 10 will get merged into blocks 4 & 5 respectively which
 enables CSE, DCE and other optimizations to occur on a larger block
 of code.    

References calculate_dominance_info(), CDI_DOMINATORS, cfun, changed, dump_file, dump_flags, EDGE_COUNT, EDGE_PRED, EDGE_SUCC, find_block_to_duplicate_for_splitting_paths(), free_original_copy_tables(), ggc_alloc(), basic_block_def::index, initialize_original_copy_tables(), is_feasible_trace(), loop::latch, LI_FROM_INNERMOST, loop_optimizer_finalize(), loop_optimizer_init(), LOOPS_HAVE_RECORDED_EXITS, LOOPS_NEED_FIXUP, LOOPS_NORMAL, loops_state_set(), optimize_loop_for_speed_p(), TDF_DETAILS, and transform_duplicate().

Referenced by execute_split_paths().