<commit_before>/*
 * Project:     libFIRM
 * File name:   ir/opt/ldstopt.c
 * Purpose:     load store optimizations
 * Author:
 * Created:
 * CVS-ID:      $Id$
 * Copyright:   (c) 1998-2004 <NAME>
 * Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
 */
# include "irnode_t.h"
# include "irgraph_t.h"
# include "irmode_t.h"
# include "iropt_t.h"
# include "ircons_t.h"
# include "irgmod.h"
# include "irgwalk.h"
# include "irvrfy.h"
# include "tv_t.h"
# include "dbginfo_t.h"
# include "iropt_dbg.h"
# include "irflag_t.h"
# include "array.h"
# include "firmstat.h"

#undef IMAX
#define IMAX(a,b)	((a) > (b) ? (a) : (b))

#define MAX_PROJ	IMAX(pn_Load_max, pn_Store_max)

/**
 * walker environment
 */
typedef struct _walk_env_t {
  struct obstack obst;		/**< list of all stores */
  int changes;
} walk_env_t;

/**
 * a Load/Store info
 */
typedef struct _ldst_info_t {
  ir_node *projs[MAX_PROJ];	/**< list of Proj's of this node */
  ir_node *exc_block;           /**< the exception block if available */
  int     exc_idx;              /**< predecessor index in the exception block */
} ldst_info_t;

/**
 * flags for control flow
 */
enum block_flags_t {
  BLOCK_HAS_COND = 1,      /**< Block has conditional control flow */
  BLOCK_HAS_EXC  = 2       /**< Block has exceptionl control flow */
};

/**
 * a Block info
 */
typedef struct _block_info_t {
  unsigned flags;               /**< flags for the block */
} block_info_t;

/**
 * walker, clears all links first
 */
static void init_links(ir_node *n, void *env)
{
  set_irn_link(n, NULL);
}

/**
 * get the Load/Store info of a node
 */
static ldst_info_t *get_ldst_info(ir_node *node, walk_env_t *env)
{
  ldst_info_t *info = get_irn_link(node);

  if (! info) {
    info = obstack_alloc(&env->obst, sizeof(*info));

    memset(info, 0, sizeof(*info));

    set_irn_link(node, info);
  }
  return info;
}

/**
 * get the Block info of a node
 */
static block_info_t *get_block_info(ir_node *node, walk_env_t *env)
{
  block_info_t *info = get_irn_link(node);

  if (! info) {
    info = obstack_alloc(&env->obst, sizeof(*info));

    memset(info, 0, sizeof(*info));

    set_irn_link(node, info);
  }
  return info;
}

/**
 * update the projection info for a Load/Store
 */
static int update_projs(ldst_info_t *info, ir_node *proj)
{
  long nr = get_Proj_proj(proj);

  assert(0 <= nr && nr <= MAX_PROJ && "Wrong proj from LoadStore");

  if (info->projs[nr]) {
    /* there is already one, do CSE */
    exchange(proj, info->projs[nr]);
    return 1;
  }
  else {
    info->projs[nr] = proj;
    return 0;
  }
}

/**
 * update the exception block info for a Load/Store
 */
static int update_exc(ldst_info_t *info, ir_node *block, int pos)
{
  assert(info->exc_block == NULL && "more than one exception block found");

  info->exc_block = block;
  info->exc_idx   = pos;
  return 0;
}

#define get_irn_out_n(node)     (unsigned)get_irn_link(node)
#define set_irn_out_n(node, n)  set_irn_link(adr, (void *)(n))

/**
 * walker, collects all Load/Store/Proj nodes
 *
 * walks form Start -> End
 */
static void collect_nodes(ir_node *node, void *env)
{
  ir_node     *pred;
  ldst_info_t *ldst_info;
  walk_env_t  *wenv = env;

  if (get_irn_op(node) == op_Proj) {
    ir_node *adr;
    ir_op *op;

    pred = get_Proj_pred(node);
    op   = get_irn_op(pred);

    if (op == op_Load) {
      adr       = get_Load_ptr(pred);
      ldst_info = get_ldst_info(pred, wenv);

      wenv->changes |= update_projs(ldst_info, node);

      set_irn_out_n(adr, get_irn_out_n(adr) + 1);
    }
    else if (op == op_Store) {
      adr       = get_Store_ptr(pred);
      ldst_info = get_ldst_info(pred, wenv);

      wenv->changes |= update_projs(ldst_info, node);

      set_irn_out_n(adr, get_irn_out_n(adr) + 1);
    }
  }
  else if (get_irn_op(node) == op_Block) { /* check, if it's an exception block */
    int i, n;

    for (i = 0, n = get_Block_n_cfgpreds(node); i < n; ++i) {
      ir_node      *pred_block;
      block_info_t *bl_info;

      pred = skip_Proj(get_Block_cfgpred(node, i));

      /* ignore Bad predecessors, they will be removed later */
      if (is_Bad(pred))
	continue;

      pred_block = get_nodes_block(pred);
      bl_info    = get_block_info(pred_block, wenv);

      if (is_fragile_op(pred))
	bl_info->flags |= BLOCK_HAS_EXC;
      else if (is_forking_op(pred))
	bl_info->flags |= BLOCK_HAS_COND;

      if (get_irn_op(pred) == op_Load || get_irn_op(pred) == op_Store) {
        ldst_info = get_ldst_info(pred, wenv);<commit_msg>Fixed address count calculation. Every Load was visited twice, so the count was wrong.<commit_after>/*
 * Project:     libFIRM
 * File name:   ir/opt/ldstopt.c
 * Purpose:     load store optimizations
 * Author:
 * Created:
 * CVS-ID:      $Id$
 * Copyright:   (c) 1998-2004 Universitt Karlsruhe
 * Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
 */
# include "irnode_t.h"
# include "irgraph_t.h"
# include "irmode_t.h"
# include "iropt_t.h"
# include "ircons_t.h"
# include "irgmod.h"
# include "irgwalk.h"
# include "irvrfy.h"
# include "tv_t.h"
# include "dbginfo_t.h"
# include "iropt_dbg.h"
# include "irflag_t.h"
# include "array.h"
# include "firmstat.h"

#undef IMAX
#define IMAX(a,b)	((a) > (b) ? (a) : (b))

#define MAX_PROJ	IMAX(pn_Load_max, pn_Store_max)

/**
 * walker environment
 */
typedef struct _walk_env_t {
  struct obstack obst;		/**< list of all stores */
  int changes;
} walk_env_t;

/**
 * flags for Load/Store
 */
enum ldst_flags_t {
  LDST_VISITED = 1              /**< if set, this Load/Store is already visited */
};

/**
 * a Load/Store info
 */
typedef struct _ldst_info_t {
  ir_node  *projs[MAX_PROJ];    /**< list of Proj's of this node */
  ir_node  *exc_block;          /**< the exception block if available */
  int      exc_idx;             /**< predecessor index in the exception block */
  unsigned flags;               /**< flags */
} ldst_info_t;

/**
 * flags for control flow
 */
enum block_flags_t {
  BLOCK_HAS_COND = 1,      /**< Block has conditional control flow */
  BLOCK_HAS_EXC  = 2       /**< Block has exceptionl control flow */
};

/**
 * a Block info
 */
typedef struct _block_info_t {
  unsigned flags;               /**< flags for the block */
} block_info_t;

/**
 * walker, clears all links first
 */
static void init_links(ir_node *n, void *env)
{
  set_irn_link(n, NULL);
}

/**
 * get the Load/Store info of a node
 */
static ldst_info_t *get_ldst_info(ir_node *node, walk_env_t *env)
{
  ldst_info_t *info = get_irn_link(node);

  if (! info) {
    info = obstack_alloc(&env->obst, sizeof(*info));

    memset(info, 0, sizeof(*info));

    set_irn_link(node, info);
  }
  return info;
}

/**
 * get the Block info of a node
 */
static block_info_t *get_block_info(ir_node *node, walk_env_t *env)
{
  block_info_t *info = get_irn_link(node);

  if (! info) {
    info = obstack_alloc(&env->obst, sizeof(*info));

    memset(info, 0, sizeof(*info));

    set_irn_link(node, info);
  }
  return info;
}

/**
 * update the projection info for a Load/Store
 */
static int update_projs(ldst_info_t *info, ir_node *proj)
{
  long nr = get_Proj_proj(proj);

  assert(0 <= nr && nr <= MAX_PROJ && "Wrong proj from LoadStore");

  if (info->projs[nr]) {
    /* there is already one, do CSE */
    exchange(proj, info->projs[nr]);
    return 1;
  }
  else {
    info->projs[nr] = proj;
    return 0;
  }
}

/**
 * update the exception block info for a Load/Store
 */
static int update_exc(ldst_info_t *info, ir_node *block, int pos)
{
  assert(info->exc_block == NULL && "more than one exception block found");

  info->exc_block = block;
  info->exc_idx   = pos;
  return 0;
}

#define get_irn_out_n(node)     (unsigned)get_irn_link(node)
#define set_irn_out_n(node, n)  set_irn_link(adr, (void *)(n))

/**
 * walker, collects all Load/Store/Proj nodes
 *
 * walks form Start -> End
 */
static void collect_nodes(ir_node *node, void *env)
{
  ir_op       *op = get_irn_op(node);
  ir_node     *pred;
  ldst_info_t *ldst_info;
  walk_env_t  *wenv = env;

  if (op == op_Proj) {
    ir_node *adr;
    ir_op *op;

    pred = get_Proj_pred(node);
    op   = get_irn_op(pred);

    if (op == op_Load) {
      ldst_info = get_ldst_info(pred, wenv);

      wenv->changes |= update_projs(ldst_info, node);

      if ((ldst_info->flags & LDST_VISITED) == 0) {
        adr = get_Load_ptr(pred);
        set_irn_out_n(adr, get_irn_out_n(adr) + 1);

        ldst_info->flags |= LDST_VISITED;
      }
    }
    else if (op == op_Store) {
      ldst_info = get_ldst_info(pred, wenv);

      wenv->changes |= update_projs(ldst_info, node);

      if ((ldst_info->flags & LDST_VISITED) == 0) {
        adr = get_Store_ptr(pred);
        set_irn_out_n(adr, get_irn_out_n(adr) + 1);

        ldst_info->flags |= LDST_VISITED;
      }
    }
  }
  else if (op == op_Block) { /* check, if it's an exception block */
    int i, n;

    for (i = 0, n = get_Block_n_cfgpreds(node); i < n; ++i) {
      ir_node      *pred_block;
      block_info_t *bl_info;

      pred = skip_Proj(get_Block_cfgpred(node, i));

      /* ignore Bad predecessors, they will be removed later */
      if (is_Bad(pred))
	continue;

      pred_block = get_nodes_block(pred);
      bl_info    = get_block_info(pred_block, wenv);

      if (is_fragile_op(pred))
	bl_info->flags |= BLOCK_HAS_EXC;
      else if (is_forking_op(pred))
	bl_info->flags |= BLOCK_HAS_COND;

      if (get_irn_op(pred) == op_Load || get_irn_op(pred) == op_Store) {
        ldst_info = get_ldst_info(pred, wenv);
{'fraction_non_alphanumeric': 0.13992459153749476, 'fraction_numerical': 0.004294093003770423, 'mean_word_length': 3.018939393939394, 'pattern_counts': {'":': 0, '<': 26, '<?xml version=': 0, '>': 36, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3464194', 'n_tokens_mistral': 3830, 'n_tokens_neox': 3686, 'n_words': 881}