Skip to content

Commit

Permalink
Implement def-use chain
Browse files Browse the repository at this point in the history
Implement a new structure for def-use chain called "uc_node_t".
"uc_node_t" is stored within "struct var", includes "insn" element that
records the instruction using the variable which the use chain belongs
to.

Simplify CSE procedure with use chain information. We build the def-use
chain information by "build_use_chain" function before the optimizing
phase. In addtion, When the instructions are eliminated by CSE, we
delete its use chain nodes from both variables("rs1", "rs2") at the same
time.

The CSE method has been modified. When the first pair of instructions is
found, the use chain is utilized to search for identical ADD
instructions. Subsequently, the next instruction is verified to ensure
it match our target. After removing the instruction, utilize the use
chain to find the next target instruction.
  • Loading branch information
nosba0957 committed Nov 4, 2024
1 parent 6261f31 commit 4b759d9
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 38 deletions.
12 changes: 10 additions & 2 deletions src/defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,14 @@ struct ref_block_list {

typedef struct ref_block_list ref_block_list_t;

typedef struct insn insn_t;

typedef struct use_chain_node {
insn_t *insn;
struct use_chain_node *next;
struct use_chain_node *prev;
} uc_node_t;

struct var {
char type_name[MAX_TYPE_LEN];
char var_name[MAX_VAR_LEN];
Expand All @@ -174,6 +182,8 @@ struct var {
int subscripts_idx;
rename_t rename;
ref_block_list_t ref_block_list; /* blocks which kill variable */
uc_node_t *use_chain_head;
uc_node_t *use_chain_tail;
struct insn *last_assign;
int consumed;
bool is_ternary_ret;
Expand Down Expand Up @@ -316,8 +326,6 @@ struct insn {
char str[64];
};

typedef struct insn insn_t;

typedef struct {
insn_t *head;
insn_t *tail;
Expand Down
136 changes: 100 additions & 36 deletions src/ssa.c
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,49 @@ void build_rdf()
free(args);
}

void use_chain_add_tail(insn_t *i, var_t *var)
{
uc_node_t *n = calloc(1, sizeof(uc_node_t));
n->insn = i;
if (!var->use_chain_head)
var->use_chain_head = n;
else
var->use_chain_tail->next = n;
n->prev = var->use_chain_tail;
var->use_chain_tail = n;
}

void use_chain_delete(uc_node_t *node, var_t *var)
{
if (node->prev)
node->prev->next = node->next;
else {
var->use_chain_head = node->next;
node->next->prev = NULL;
}
if (node->next)
node->next->prev = node->prev;
else {
var->use_chain_tail = node->prev;
node->prev->next = NULL;
}
free(node);
}

void build_use_chain()
{
for (fn_t *fn = FUNC_LIST.head; fn; fn = fn->next) {
for (basic_block_t *bb = fn->bbs; bb; bb = bb->rpo_next) {
for (insn_t *i = bb->insn_list.head; i; i = i->next) {
if (i->rs1)
use_chain_add_tail(i, i->rs1);
if (i->rs2)
use_chain_add_tail(i, i->rs2);
}
}
}
}

bool var_check_killed(var_t *var, basic_block_t *bb)
{
for (int i = 0; i < bb->live_kill_idx; i++) {
Expand Down Expand Up @@ -1170,63 +1213,82 @@ void ssa_build(int dump_ir)
}

/* Common Subexpression Elimination (CSE) */
/* TODO: simplify with def-use chain */
/* TODO: release detached insns node */
bool cse(insn_t *insn, basic_block_t *bb)
{
if (insn->opcode != OP_read)
return false;

insn_t *prev = insn->prev;

if (!prev)
return false;
if (prev->opcode != OP_add)
return false;
if (prev->rd != insn->rs1)
return false;

var_t *def = NULL, *base = prev->rs1, *idx = prev->rs2;
var_t *def = insn->rd, *base = prev->rs1, *idx = prev->rs2;
if (base->is_global || idx->is_global)
return false;

insn_t *i = prev;
for (basic_block_t *b = bb;; b = b->idom) {
uc_node_t *rs1_delete_node = NULL;
uc_node_t *rs2_delete_node = NULL;
for (uc_node_t *node = base->use_chain_head; node; node = node->next) {
insn_t *i = node->insn;

/* Delete the use chain nodes found in the last loop */
if (rs1_delete_node) {
use_chain_delete(rs1_delete_node, rs1_delete_node->insn->rs1);
rs1_delete_node = NULL;
}
if (rs2_delete_node) {
use_chain_delete(rs2_delete_node, rs2_delete_node->insn->rs2);
rs2_delete_node = NULL;
}
if (!i)
i = b->insn_list.tail;

for (; i; i = i->prev) {
if (i == prev)
continue;
if (i->opcode != OP_add)
continue;
if (!i->next)
continue;
if (i->next->opcode != OP_read)
continue;
if (i->rs1 != base || i->rs2 != idx)
continue;
def = i->next->rd;
continue;
if (i == prev)
continue;
if (i->opcode != OP_add)
continue;
if (!i->next)
continue;
if (i->next->opcode != OP_read)
continue;
if (i->rs1 != base || i->rs2 != idx)
continue;
basic_block_t *i_bb = i->belong_to;
bool check_dom = 0;
/* Check if the instructions are under the same dominate tree */
for (;; i_bb = i_bb->idom) {
if (i_bb == bb) {
check_dom = true;
break;
}
if (i_bb == i_bb->idom)
break;
}
if (def)
break;
if (b->idom == b)
break;
}

if (!def)
return false;
if (!check_dom)
continue;

if (prev->prev) {
insn->prev = prev->prev;
prev->prev->next = insn;
} else {
bb->insn_list.head = insn;
insn->prev = NULL;
i->next->opcode = OP_assign;
i->next->rs1 = def;
if (i->prev) {
i->prev->next = i->next;
i->next->prev = i->prev;
} else {
i->belong_to->insn_list.head = i->next;
i->next->prev = NULL;
}
i->next->opcode = OP_assign;
i->next->rs1 = def;
/* Prepare information for deleting use chain nodes */
rs1_delete_node = node;
for (rs2_delete_node = i->rs2->use_chain_head;
rs2_delete_node->insn != rs1_delete_node->insn;
rs2_delete_node = rs2_delete_node->next)
;
}

insn->opcode = OP_assign;
insn->rs1 = def;
return true;
}

Expand Down Expand Up @@ -1466,6 +1528,8 @@ void optimize()
build_rdom();
build_rdf();

build_use_chain();

for (fn_t *fn = FUNC_LIST.head; fn; fn = fn->next) {
/* basic block level (control flow) optimizations */

Expand Down

0 comments on commit 4b759d9

Please sign in to comment.