Skip to content

Commit 1eb0e8d

Browse files
committed
Implement def-use chain
Implement a new structure for def-use chain called "user_t". "user_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_users" 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.
1 parent 16484f2 commit 1eb0e8d

File tree

2 files changed

+109
-39
lines changed

2 files changed

+109
-39
lines changed

src/defs.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,14 @@ struct ref_block_list {
157157

158158
typedef struct ref_block_list ref_block_list_t;
159159

160+
typedef struct insn insn_t;
161+
162+
typedef struct use_chain_node {
163+
insn_t *insn;
164+
struct use_chain_node *next;
165+
struct use_chain_node *prev;
166+
} user_t;
167+
160168
struct var {
161169
char type_name[MAX_TYPE_LEN];
162170
char var_name[MAX_VAR_LEN];
@@ -174,6 +182,8 @@ struct var {
174182
int subscripts_idx;
175183
rename_t rename;
176184
ref_block_list_t ref_block_list; /* blocks which kill variable */
185+
user_t *users_head;
186+
user_t *users_tail;
177187
struct insn *last_assign;
178188
int consumed;
179189
bool is_ternary_ret;
@@ -316,8 +326,6 @@ struct insn {
316326
char str[64];
317327
};
318328

319-
typedef struct insn insn_t;
320-
321329
typedef struct {
322330
insn_t *head;
323331
insn_t *tail;

src/ssa.c

Lines changed: 99 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,49 @@ void build_rdf()
401401
free(args);
402402
}
403403

404+
void users_add_tail(insn_t *i, var_t *var)
405+
{
406+
user_t *u = calloc(1, sizeof(user_t));
407+
u->insn = i;
408+
if (!var->users_head)
409+
var->users_head = u;
410+
else
411+
var->users_tail->next = u;
412+
u->prev = var->users_tail;
413+
var->users_tail = u;
414+
}
415+
416+
void users_delete(user_t *u, var_t *var)
417+
{
418+
if (u->prev)
419+
u->prev->next = u->next;
420+
else {
421+
var->users_head = u->next;
422+
u->next->prev = NULL;
423+
}
424+
if (u->next)
425+
u->next->prev = u->prev;
426+
else {
427+
var->users_tail = u->prev;
428+
u->prev->next = NULL;
429+
}
430+
free(u);
431+
}
432+
433+
void build_users()
434+
{
435+
for (fn_t *fn = FUNC_LIST.head; fn; fn = fn->next) {
436+
for (basic_block_t *bb = fn->bbs; bb; bb = bb->rpo_next) {
437+
for (insn_t *i = bb->insn_list.head; i; i = i->next) {
438+
if (i->rs1)
439+
users_add_tail(i, i->rs1);
440+
if (i->rs2)
441+
users_add_tail(i, i->rs2);
442+
}
443+
}
444+
}
445+
}
446+
404447
bool var_check_killed(var_t *var, basic_block_t *bb)
405448
{
406449
for (int i = 0; i < bb->live_kill_idx; i++) {
@@ -1170,63 +1213,80 @@ void ssa_build(int dump_ir)
11701213
}
11711214

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

11801222
insn_t *prev = insn->prev;
1181-
11821223
if (!prev)
11831224
return false;
11841225
if (prev->opcode != OP_add)
11851226
return false;
11861227
if (prev->rd != insn->rs1)
11871228
return false;
11881229

1189-
var_t *def = NULL, *base = prev->rs1, *idx = prev->rs2;
1230+
var_t *def = insn->rd, *base = prev->rs1, *idx = prev->rs2;
11901231
if (base->is_global || idx->is_global)
11911232
return false;
11921233

1193-
insn_t *i = prev;
1194-
for (basic_block_t *b = bb;; b = b->idom) {
1195-
if (!i)
1196-
i = b->insn_list.tail;
1197-
1198-
for (; i; i = i->prev) {
1199-
if (i == prev)
1200-
continue;
1201-
if (i->opcode != OP_add)
1202-
continue;
1203-
if (!i->next)
1204-
continue;
1205-
if (i->next->opcode != OP_read)
1206-
continue;
1207-
if (i->rs1 != base || i->rs2 != idx)
1208-
continue;
1209-
def = i->next->rd;
1210-
}
1211-
if (def)
1212-
break;
1213-
if (b->idom == b)
1214-
break;
1215-
}
1234+
user_t *rs1_delete_user = NULL;
1235+
user_t *rs2_delete_user = NULL;
1236+
for (user_t *user = base->users_head; user; user = user->next) {
1237+
insn_t *i = user->insn;
12161238

1217-
if (!def)
1218-
return false;
1239+
/* Delete the use chain nodes found in the last loop */
1240+
if (rs1_delete_user) {
1241+
users_delete(rs1_delete_user, rs1_delete_user->insn->rs1);
1242+
rs1_delete_user = NULL;
1243+
}
1244+
if (rs2_delete_user) {
1245+
users_delete(rs2_delete_user, rs2_delete_user->insn->rs2);
1246+
rs2_delete_user = NULL;
1247+
}
1248+
if (i == prev)
1249+
continue;
1250+
if (i->opcode != OP_add)
1251+
continue;
1252+
if (!i->next)
1253+
continue;
1254+
if (i->next->opcode != OP_read)
1255+
continue;
1256+
if (i->rs1 != base || i->rs2 != idx)
1257+
continue;
1258+
basic_block_t *i_bb = i->belong_to;
1259+
bool check_dom = 0;
1260+
/* Check if the instructions are under the same dominate tree */
1261+
for (;; i_bb = i_bb->idom) {
1262+
if (i_bb == bb) {
1263+
check_dom = true;
1264+
break;
1265+
}
1266+
if (i_bb == i_bb->idom)
1267+
break;
1268+
}
1269+
if (!check_dom)
1270+
continue;
12191271

1220-
if (prev->prev) {
1221-
insn->prev = prev->prev;
1222-
prev->prev->next = insn;
1223-
} else {
1224-
bb->insn_list.head = insn;
1225-
insn->prev = NULL;
1272+
i->next->opcode = OP_assign;
1273+
i->next->rs1 = def;
1274+
if (i->prev) {
1275+
i->prev->next = i->next;
1276+
i->next->prev = i->prev;
1277+
} else {
1278+
i->belong_to->insn_list.head = i->next;
1279+
i->next->prev = NULL;
1280+
}
1281+
i->next->opcode = OP_assign;
1282+
i->next->rs1 = def;
1283+
/* Prepare information for deleting use chain nodes */
1284+
rs1_delete_user = user;
1285+
for (rs2_delete_user = i->rs2->users_head;
1286+
rs2_delete_user->insn != rs1_delete_user->insn;
1287+
rs2_delete_user = rs2_delete_user->next)
1288+
;
12261289
}
1227-
1228-
insn->opcode = OP_assign;
1229-
insn->rs1 = def;
12301290
return true;
12311291
}
12321292

@@ -1466,6 +1526,8 @@ void optimize()
14661526
build_rdom();
14671527
build_rdf();
14681528

1529+
build_users();
1530+
14691531
for (fn_t *fn = FUNC_LIST.head; fn; fn = fn->next) {
14701532
/* basic block level (control flow) optimizations */
14711533

0 commit comments

Comments
 (0)