<commit_before>/*
 * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
 *
 * This file is part of libFirm.
 *
 * This file may be distributed and/or modified under the terms of the
 * GNU General Public License version 2 as published by the Free Software
 * Foundation and appearing in the file LICENSE.GPL included in the
 * packaging of this file.
 *
 * Licensees holding valid libFirm Professional Edition licenses may use
 * this file in accordance with the libFirm Commercial License.
 * Agreement provided with the Software.
 *
 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE.
 */

/**
 * @file
 * @brief       Methods to compute when a value will be used again.
 * @author      <NAME>, <NAME>
 * @date        27.06.2005
 * @version     $Id$
 */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <limits.h>
#include <stdlib.h>

#include "config.h"
#include "obst.h"
#include "pmap.h"
#include "debug.h"

#include "irgwalk.h"
#include "irnode_t.h"
#include "ircons_t.h"
#include "irgraph_t.h"
#include "iredges_t.h"
#include "irdom_t.h"

#include "be_t.h"
#include "beutil.h"
#include "belive_t.h"
#include "benode_t.h"
#include "besched_t.h"
#include "beirgmod.h"
#include "bearch_t.h"
#include "beuses.h"

#define SCAN_INTERBLOCK_USES

typedef struct _be_use_t {
	const ir_node *block;
	const ir_node *node;
	int outermost_loop;
	unsigned next_use;
	unsigned visited;
} be_use_t;

struct _be_uses_t {
  	set *uses;
	ir_graph *irg;
	const be_lv_t *lv;
	unsigned visited_counter;
	DEBUG_ONLY(firm_dbg_module_t *dbg;)
};

static int cmp_use(const void *a, const void *b, size_t n)
{
	const be_use_t *p = a;
	const be_use_t *q = b;
	(void) n;

	return !(p->block == q->block && p->node == q->node);
}

static be_next_use_t get_next_use(be_uses_t *env, ir_node *from,
								  unsigned from_step, const ir_node *def,
								  int skip_from_uses);

static const be_use_t *get_or_set_use_block(be_uses_t *env,
                                            const ir_node *block,
                                            const ir_node *def)
{
	unsigned hash = HASH_COMBINE(hash_irn(block), hash_irn(def));
	be_use_t temp;
	be_use_t* result;

	temp.block = block;
	temp.node = def;
	result = set_find(env->uses, &temp, sizeof(temp), hash);

	if(result == NULL) {
		// insert templ first as we might end in a loop in the get_next_use
		// call otherwise
		temp.next_use = USES_INFINITY;
		temp.outermost_loop = -1;
		temp.visited = 0;
		result = set_insert(env->uses, &temp, sizeof(temp), hash);
	}

	if(result->outermost_loop < 0 && result->visited < env->visited_counter) {
		be_next_use_t next_use;

		result->visited = env->visited_counter;
		next_use = get_next_use(env, sched_first(block), 0, def, 0);
		if(next_use.outermost_loop >= 0) {
			result->next_use = next_use.time;
			result->outermost_loop = next_use.outermost_loop;
			DBG((env->dbg, LEVEL_5, "Setting nextuse of %+F in block %+F to %u (outermostloop %d)\n", def, block, result->next_use, result->outermost_loop));
		}
	}

	return result;
}

static int be_is_phi_argument(const ir_node *block, const ir_node *def)
{
	ir_node *node;
	ir_node *succ_block = NULL;
	const ir_edge_t *edge;
	int arity, i;

#if 0
	if(get_irn_n_edges_kind(block, EDGE_KIND_BLOCK) > 1)
		return 0;
#endif

	foreach_block_succ(block, edge) {
		succ_block = get_edge_src_irn(edge);
		break;
	}

	arity = get_Block_n_cfgpreds(succ_block);
	if(arity <= 1)
		return 0;

	for(i = 0; i < arity; ++i) {
		if(get_Block_cfgpred_block(succ_block, i) == block)
			break;
	}
	assert(i < arity);

	sched_foreach(succ_block, node) {
		ir_node *arg;
<commit_msg>Prevent beuses from choking on basic blocks without control flow successors.<commit_after>/*
 * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
 *
 * This file is part of libFirm.
 *
 * This file may be distributed and/or modified under the terms of the
 * GNU General Public License version 2 as published by the Free Software
 * Foundation and appearing in the file LICENSE.GPL included in the
 * packaging of this file.
 *
 * Licensees holding valid libFirm Professional Edition licenses may use
 * this file in accordance with the libFirm Commercial License.
 * Agreement provided with the Software.
 *
 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE.
 */

/**
 * @file
 * @brief       Methods to compute when a value will be used again.
 * @author      <NAME>, <NAME>
 * @date        27.06.2005
 * @version     $Id$
 */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <limits.h>
#include <stdlib.h>

#include "config.h"
#include "obst.h"
#include "pmap.h"
#include "debug.h"

#include "irgwalk.h"
#include "irnode_t.h"
#include "ircons_t.h"
#include "irgraph_t.h"
#include "iredges_t.h"
#include "irdom_t.h"

#include "be_t.h"
#include "beutil.h"
#include "belive_t.h"
#include "benode_t.h"
#include "besched_t.h"
#include "beirgmod.h"
#include "bearch_t.h"
#include "beuses.h"

#define SCAN_INTERBLOCK_USES

typedef struct _be_use_t {
	const ir_node *block;
	const ir_node *node;
	int outermost_loop;
	unsigned next_use;
	unsigned visited;
} be_use_t;

struct _be_uses_t {
  	set *uses;
	ir_graph *irg;
	const be_lv_t *lv;
	unsigned visited_counter;
	DEBUG_ONLY(firm_dbg_module_t *dbg;)
};

static int cmp_use(const void *a, const void *b, size_t n)
{
	const be_use_t *p = a;
	const be_use_t *q = b;
	(void) n;

	return !(p->block == q->block && p->node == q->node);
}

static be_next_use_t get_next_use(be_uses_t *env, ir_node *from,
								  unsigned from_step, const ir_node *def,
								  int skip_from_uses);

static const be_use_t *get_or_set_use_block(be_uses_t *env,
                                            const ir_node *block,
                                            const ir_node *def)
{
	unsigned hash = HASH_COMBINE(hash_irn(block), hash_irn(def));
	be_use_t temp;
	be_use_t* result;

	temp.block = block;
	temp.node = def;
	result = set_find(env->uses, &temp, sizeof(temp), hash);

	if(result == NULL) {
		// insert templ first as we might end in a loop in the get_next_use
		// call otherwise
		temp.next_use = USES_INFINITY;
		temp.outermost_loop = -1;
		temp.visited = 0;
		result = set_insert(env->uses, &temp, sizeof(temp), hash);
	}

	if(result->outermost_loop < 0 && result->visited < env->visited_counter) {
		be_next_use_t next_use;

		result->visited = env->visited_counter;
		next_use = get_next_use(env, sched_first(block), 0, def, 0);
		if(next_use.outermost_loop >= 0) {
			result->next_use = next_use.time;
			result->outermost_loop = next_use.outermost_loop;
			DBG((env->dbg, LEVEL_5, "Setting nextuse of %+F in block %+F to %u (outermostloop %d)\n", def, block, result->next_use, result->outermost_loop));
		}
	}

	return result;
}

static int be_is_phi_argument(const ir_node *block, const ir_node *def)
{
	ir_node *node;
	ir_node *succ_block = NULL;
	const ir_edge_t *edge;
	int arity, i;

#if 1
	if (get_irn_n_edges_kind(block, EDGE_KIND_BLOCK) < 1)
#else
	if (get_irn_n_edges_kind(block, EDGE_KIND_BLOCK) != 1)
#endif
		return 0;

	foreach_block_succ(block, edge) {
		succ_block = get_edge_src_irn(edge);
		break;
	}

	arity = get_Block_n_cfgpreds(succ_block);
	if(arity <= 1)
		return 0;

	for(i = 0; i < arity; ++i) {
		if(get_Block_cfgpred_block(succ_block, i) == block)
			break;
	}
	assert(i < arity);

	sched_foreach(succ_block, node) {
		ir_node *arg;

{'fraction_non_alphanumeric': 0.11687797147385103, 'fraction_numerical': 0.008055995773903856, 'mean_word_length': 3.733125, 'pattern_counts': {'":': 0, '<': 22, '<?xml version=': 0, '>': 46, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5658401', 'n_tokens_mistral': 2987, 'n_tokens_neox': 2817, 'n_words': 780}