GCC Middle and Back End API Reference
gimple-loop-jam.cc File Reference
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "tree-pass.h"
#include "backend.h"
#include "tree.h"
#include "gimple.h"
#include "ssa.h"
#include "fold-const.h"
#include "tree-cfg.h"
#include "tree-ssa.h"
#include "tree-ssa-loop-niter.h"
#include "tree-ssa-loop.h"
#include "tree-ssa-loop-manip.h"
#include "cfgloop.h"
#include "tree-scalar-evolution.h"
#include "gimple-iterator.h"
#include "cfghooks.h"
#include "tree-data-ref.h"
#include "tree-ssa-loop-ivopts.h"
#include "tree-vectorizer.h"
#include "tree-ssa-sccvn.h"
#include "tree-cfgcleanup.h"
Include dependency graph for gimple-loop-jam.cc:


static void merge_loop_tree (class loop *loop, class loop *old)
static bool bb_prevents_fusion_p (basic_block bb)
static bool unroll_jam_possible_p (class loop *outer, class loop *loop)
static void fuse_loops (class loop *loop)
static bool any_access_function_variant_p (const struct data_reference *a, const class loop *loop_nest)
static bool adjust_unroll_factor (class loop *inner, struct data_dependence_relation *ddr, unsigned *unroll, unsigned *profit_unroll, unsigned *removed)
static unsigned int tree_loop_unroll_and_jam (void)
gimple_opt_passmake_pass_loop_jam (gcc::context *ctxt)

Function Documentation

◆ adjust_unroll_factor()

static bool adjust_unroll_factor ( class loop * inner,
struct data_dependence_relation * ddr,
unsigned * unroll,
unsigned * profit_unroll,
unsigned * removed )
Returns true if the distance in DDR can be determined and adjusts
the unroll factor in *UNROLL to make unrolling valid for that distance.
Otherwise return false.  DDR is with respect to the outer loop of INNER.

If this data dep can lead to a removed memory reference, increment
*REMOVED and adjust *PROFIT_UNROLL to be the necessary unroll factor
for this to happen.   

References any_access_function_variant_p(), chrec_known, DDR_A, DDR_ARE_DEPENDENT, DDR_B, DDR_DIST_VECTS, DDR_NB_LOOPS, DDR_NUM_DIST_VECTS, DR_IS_READ, FOR_EACH_VEC_ELT, gcc_unreachable, ggc_alloc(), i, loop::inner, lambda_vector_lexico_pos(), lambda_vector_zerop(), MAX, and loop::unroll.

Referenced by tree_loop_unroll_and_jam().

◆ any_access_function_variant_p()

static bool any_access_function_variant_p ( const struct data_reference * a,
const class loop * loop_nest )
Return true if any of the access functions for dataref A
isn't invariant with respect to loop LOOP_NEST.   

References a, DR_ACCESS_FNS, evolution_function_is_invariant_p(), and loop::num.

Referenced by adjust_unroll_factor().

◆ bb_prevents_fusion_p()

static bool bb_prevents_fusion_p ( basic_block bb)
BB is part of the outer loop of an unroll-and-jam situation.
Check if any statements therein would prevent the transformation.   

References g, gimple_has_side_effects(), gimple_vdef(), gsi_end_p(), gsi_next(), gsi_start_bb(), and gsi_stmt().

Referenced by unroll_jam_possible_p().

◆ fuse_loops()

◆ make_pass_loop_jam()

gimple_opt_pass * make_pass_loop_jam ( gcc::context * ctxt)

References ggc_alloc().

◆ merge_loop_tree()

static void merge_loop_tree ( class loop * loop,
class loop * old )
Loop unroll-and-jam.
   Copyright (C) 2017-2024 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
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
Unroll and Jam transformation
  This is a combination of two transformations, where the second
  is not always valid.  It's applicable if a loop nest has redundancies
  over the iterations of an outer loop while not having that with
  an inner loop.

  Given this nest:
      for (i) {
        for (j) {

  first unroll:
      for (i by 2) {
        for (j) {
        for (j) {

  then fuse the two adjacent inner loops resulting from that:
      for (i by 2) {
        for (j) {

  As the order of evaluations of the body B changes this is valid
  only in certain situations: all distance vectors need to be forward.
  Additionally if there are multiple induction variables than just
  a counting control IV (j above) we can also deal with some situations.

  The validity is checked by unroll_jam_possible_p, and the data-dep
  testing below.

  A trivial example where the fusion is wrong would be when
  B(i,j) == x[j-1] = x[j];
      for (i by 2) {
        for (j) {
          x[j-1] = x[j];
        for (j) {
          x[j-1] = x[j];
      }  effect: move content to front by two elements
      for (i by 2) {
        for (j) {
          x[j-1] = x[j];
          x[j-1] = x[j];
      }  effect: move content to front by one element
Modify the loop tree for the fact that all code once belonging
to the OLD loop or the outer loop of OLD now is inside LOOP.   

References add_bb_to_loop(), cfun, flow_loop_tree_node_add(), flow_loop_tree_node_remove(), FOR_EACH_EDGE, free(), get_loop_body_with_size(), ggc_alloc(), i, loop_depth(), basic_block_def::loop_father, loop_outer(), n_basic_blocks_for_fn, loop::num_nodes, remove_bb_from_loops(), and rescan_loop_exit().

Referenced by fuse_loops().

◆ tree_loop_unroll_and_jam()

◆ unroll_jam_possible_p()