Commit 5224ed3c authored by Matthias Braun's avatar Matthias Braun
Browse files

beverify: Remove spillslot verifier

The verifier has been broken and therefore unused for a while, remove it
for now.
parent 30fbf37b
......@@ -28,8 +28,6 @@
#include "beirg.h"
#include "belistsched.h"
static bool my_values_interfere(const ir_node *a, const ir_node *b);
typedef struct be_verify_register_pressure_env_t_ {
be_lv_t *lv; /**< Liveness information. */
const arch_register_class_t *cls; /**< the register class to check for */
......@@ -257,299 +255,6 @@ bool be_verify_schedule(ir_graph *irg)
/*--------------------------------------------------------------------------- */
typedef struct spill_t {
ir_node *spill;
ir_entity *ent;
} spill_t;
typedef struct {
set *spills;
ir_node **reloads;
bool problem_found;
get_frame_entity_func get_frame_entity;
} be_verify_spillslots_env_t;
static int cmp_spill(const void* d1, const void* d2, size_t size)
{
(void) size;
const spill_t* s1 = (const spill_t*)d1;
const spill_t* s2 = (const spill_t*)d2;
return s1->spill != s2->spill;
}
static spill_t *find_spill(be_verify_spillslots_env_t *env, ir_node *node)
{
spill_t spill;
spill.spill = node;
return set_find(spill_t, env->spills, &spill, sizeof(spill), hash_ptr(node));
}
static spill_t *get_spill(be_verify_spillslots_env_t *env, ir_node *node, ir_entity *ent)
{
int hash = hash_ptr(node);
spill_t spill;
spill.spill = node;
spill_t *res = set_find(spill_t, env->spills, &spill, sizeof(spill), hash);
if (res == NULL) {
spill.ent = ent;
res = set_insert(spill_t, env->spills, &spill, sizeof(spill), hash);
}
return res;
}
static ir_node *get_memory_edge(const ir_node *node)
{
ir_node *result = NULL;
foreach_irn_in_r(node, i, arg) {
if (get_irn_mode(arg) == mode_M) {
assert(result == NULL);
result = arg;
}
}
return result;
}
static void collect(be_verify_spillslots_env_t *env, ir_node *node, ir_node *reload, ir_entity* ent);
static void be_check_entity(ir_node *node, ir_entity *ent)
{
if (ent == NULL)
verify_warnf(node, "%+F should have an entity assigned", node);
}
static void collect_spill(be_verify_spillslots_env_t *env, ir_node *node, ir_node *reload, ir_entity* ent)
{
ir_entity *spillent = env->get_frame_entity(node);
be_check_entity(node, spillent);
get_spill(env, node, ent);
if (spillent != ent) {
verify_warnf(node, "spill %+F has different entity than reload %+F", node, reload);
env->problem_found = true;
}
}
static void collect_memperm(be_verify_spillslots_env_t *env, ir_node *node, ir_node *reload, ir_entity* ent)
{
ir_node *memperm = get_Proj_pred(node);
unsigned out = get_Proj_num(node);
ir_entity *spillent = be_get_MemPerm_out_entity(memperm, out);
be_check_entity(memperm, spillent);
if (spillent != ent) {
verify_warnf(node, "MemPerm %+F has different entity than reload %+F", node, reload);
env->problem_found = true;
}
int hash = hash_ptr(node);
spill_t spill;
spill.spill = node;
spill_t *res = set_find(spill_t, env->spills, &spill, sizeof(spill), hash);
if (res != NULL) {
return;
}
spill.ent = spillent;
(void)set_insert(spill_t, env->spills, &spill, sizeof(spill), hash);
int arity = be_get_MemPerm_entity_arity(memperm);
for (int i = 0; i < arity; ++i) {
ir_node *const arg = get_irn_n(memperm, i);
ir_entity *const argent = be_get_MemPerm_in_entity(memperm, i);
collect(env, arg, memperm, argent);
}
}
static void collect_memphi(be_verify_spillslots_env_t *env, ir_node *node, ir_node *reload, ir_entity *ent)
{
assert(is_Phi(node));
int hash = hash_ptr(node);
spill_t spill;
spill.spill = node;
spill_t *res = set_find(spill_t, env->spills, &spill, sizeof(spill), hash);
if (res != NULL) {
return;
}
spill.ent = ent;
(void)set_insert(spill_t, env->spills, &spill, sizeof(spill), hash);
/* is 1 of the arguments a spill? */
foreach_irn_in(node, i, arg) {
collect(env, arg, reload, ent);
}
}
static void collect(be_verify_spillslots_env_t *env, ir_node *node, ir_node *reload, ir_entity* ent)
{
if (arch_irn_is(node, spill)) {
collect_spill(env, node, reload, ent);
} else if (is_Proj(node)) {
collect_memperm(env, node, reload, ent);
} else if (is_Phi(node) && get_irn_mode(node) == mode_M) {
collect_memphi(env, node, reload, ent);
}
}
/**
* This walker function searches for reloads and collects all the spills
* and memphis attached to them.
*/
static void collect_spills_walker(ir_node *node, void *data)
{
be_verify_spillslots_env_t *env = (be_verify_spillslots_env_t*)data;
if (arch_irn_is(node, reload)) {
ir_node *spill = get_memory_edge(node);
if (spill == NULL) {
verify_warnf(node, "no spill attached to reload %+F", node);
env->problem_found = true;
return;
}
ir_entity *ent = env->get_frame_entity(node);
be_check_entity(node, ent);
collect(env, spill, node, ent);
ARR_APP1(ir_node*, env->reloads, node);
}
}
static void check_spillslot_interference(be_verify_spillslots_env_t *env)
{
int spillcount = set_count(env->spills);
spill_t **spills = ALLOCAN(spill_t*, spillcount);
int s = 0;
foreach_set(env->spills, spill_t, spill) {
spills[s++] = spill;
}
assert(s == spillcount);
for (int i = 0; i < spillcount; ++i) {
spill_t *sp1 = spills[i];
for (int i2 = i+1; i2 < spillcount; ++i2) {
spill_t *sp2 = spills[i2];
if (sp1->ent != sp2->ent)
continue;
if (my_values_interfere(sp1->spill, sp2->spill)) {
verify_warnf(sp1->spill, "spillslots for %+F and %+F (in %+F) interfere",
sp1->spill, sp2->spill, get_nodes_block(sp2->spill));
env->problem_found = true;
}
}
}
}
static void check_lonely_spills(ir_node *node, void *data)
{
be_verify_spillslots_env_t *env = (be_verify_spillslots_env_t*)data;
if (arch_irn_is(node, spill)
|| (is_Proj(node) && be_is_MemPerm(get_Proj_pred(node)))) {
spill_t *spill = find_spill(env, node);
if (arch_irn_is(node, spill)) {
ir_entity *ent = env->get_frame_entity(node);
be_check_entity(node, ent);
}
if (spill == NULL)
verify_warnf(node, "%+F not connected to a reload", node);
}
}
bool be_verify_spillslots(ir_graph *irg, get_frame_entity_func get_frame_entity)
{
be_verify_spillslots_env_t env;
env.spills = new_set(cmp_spill, 10);
env.reloads = NEW_ARR_F(ir_node*, 0);
env.problem_found = false;
env.get_frame_entity = get_frame_entity;
irg_walk_graph(irg, collect_spills_walker, NULL, &env);
irg_walk_graph(irg, check_lonely_spills, NULL, &env);
check_spillslot_interference(&env);
DEL_ARR_F(env.reloads);
del_set(env.spills);
return ! env.problem_found;
}
/*--------------------------------------------------------------------------- */
/**
* Check, if two values interfere.
* @param a The first value.
* @param b The second value.
* @return 1, if a and b interfere, 0 if not.
*/
static bool my_values_interfere(const ir_node *a, const ir_node *b)
{
assert(a != b);
int a2b = value_strictly_dominates(a, b);
int b2a = value_strictly_dominates(b, a);
/* If there is no dominance relation, they do not interfere. */
if (!a2b && !b2a)
return false;
/*
* Adjust a and b so, that a dominates b if
* a dominates b or vice versa.
*/
if (b2a) {
const ir_node *t = a;
a = b;
b = t;
}
ir_node *bb = get_nodes_block(b);
/*
* Look at all usages of a.
* If there's one usage of a in the block of b, then
* we check, if this use is dominated by b, if that's true
* a and b interfere. Note that b must strictly dominate the user,
* since if b is the last user of in the block, b and a do not
* interfere.
* Uses of a not in b's block can be disobeyed, because the
* check for a being live at the end of b's block is already
* performed.
*/
foreach_out_edge(a, edge) {
const ir_node *user = get_edge_src_irn(edge);
if (b == user)
continue;
if (is_End(user))
continue;
/* in case of phi arguments we compare with the block the value comes from */
if (is_Phi(user)) {
ir_node *phiblock = get_nodes_block(user);
if (phiblock == bb)
continue;
user = get_irn_n(phiblock, get_edge_src_pos(edge));
}
if (value_strictly_dominates(b, user))
return true;
}
return false;
}
/*--------------------------------------------------------------------------- */
typedef struct be_verify_reg_alloc_env_t {
be_lv_t *lv;
bool problem_found;
......
......@@ -36,12 +36,6 @@ bool be_verify_register_pressure(ir_graph *irg,
*/
bool be_verify_schedule(ir_graph *irg);
/**
* Verify spillslots
*/
bool be_verify_spillslots(ir_graph *irg,
get_frame_entity_func get_frame_entity);
/**
* Verify register allocation: Checks that no 2 live nodes have the same
* register assigned, also checks that each scheduled node has a register
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment