issue #126: trim dmr_C by removing the simplification passes

pull/167/head
Dibyendu Majumdar 6 years ago
parent be20b2e37e
commit 37a98cdbc7

@ -255,16 +255,16 @@ set(DMR_C_SRCS
dmr_c/src/allocate.c
dmr_c/src/builtin.c
dmr_c/src/char.c
dmr_c/src/cse.c
# dmr_c/src/cse.c
dmr_c/src/expression.c
dmr_c/src/evaluate.c
dmr_c/src/expand.c
dmr_c/src/flow.c
# dmr_c/src/flow.c
dmr_c/src/inline.c
dmr_c/src/lib.c
dmr_c/src/linearize.c
dmr_c/src/liveness.c
dmr_c/src/memops.c
# dmr_c/src/memops.c
dmr_c/src/parse.c
dmr_c/src/target.c
dmr_c/src/tokenize.c
@ -272,9 +272,9 @@ set(DMR_C_SRCS
dmr_c/src/ptrlist.c
dmr_c/src/scope.c
dmr_c/src/show-parse.c
dmr_c/src/simplify.c
# dmr_c/src/simplify.c
dmr_c/src/symbol.c
dmr_c/src/unssa.c
# dmr_c/src/unssa.c
dmr_c/src/walksymbol.c
src/ravi_dmrc_parsesymbols.c
)

@ -265,31 +265,6 @@ int dmrC_simplify_flow(struct dmr_C *C, struct entrypoint *ep)
return simplify_branch_nodes(C, ep);
}
static inline void concat_user_list(struct pseudo_user_list *src, struct pseudo_user_list **dst)
{
ptrlist_concat((struct ptr_list *)src, (struct ptr_list **)dst);
}
void dmrC_convert_instruction_target(struct dmr_C *C, struct instruction *insn, pseudo_t src)
{
pseudo_t target;
struct pseudo_user *pu;
/*
* Go through the "insn->users" list and replace them all..
*/
target = insn->target;
if (target == src)
return;
FOR_EACH_PTR(target->users, pu) {
if (*pu->userp != VOID_PSEUDO(C)) {
assert(*pu->userp == target);
*pu->userp = src;
}
} END_FOR_EACH_PTR(pu);
if (dmrC_has_use_list(src))
concat_user_list(target->users, &src->users);
target->users = NULL;
}
void dmrC_convert_load_instruction(struct dmr_C *C, struct instruction *insn, pseudo_t src)
{
@ -808,72 +783,6 @@ void dmrC_simplify_symbol_usage(struct dmr_C *C, struct entrypoint *ep)
} END_FOR_EACH_PTR(pseudo);
}
static void mark_bb_reachable(struct basic_block *bb, unsigned long generation)
{
struct basic_block *child;
if (bb->generation == generation)
return;
bb->generation = generation;
FOR_EACH_PTR(bb->children, child) {
mark_bb_reachable(child, generation);
} END_FOR_EACH_PTR(child);
}
static void kill_defs(struct dmr_C *C, struct instruction *insn)
{
pseudo_t target = insn->target;
if (!dmrC_has_use_list(target))
return;
if (target->def != insn)
return;
dmrC_convert_instruction_target(C, insn, VOID_PSEUDO(C));
}
void dmrC_kill_bb(struct dmr_C *C, struct basic_block *bb)
{
struct instruction *insn;
struct basic_block *child, *parent;
FOR_EACH_PTR(bb->insns, insn) {
dmrC_kill_instruction_force(C, insn);
kill_defs(C, insn);
/*
* We kill unreachable instructions even if they
* otherwise aren't "killable" (e.g. volatile loads)
*/
} END_FOR_EACH_PTR(insn);
bb->insns = NULL;
FOR_EACH_PTR(bb->children, child) {
dmrC_remove_bb_from_list(&child->parents, bb, 0);
} END_FOR_EACH_PTR(child);
bb->children = NULL;
FOR_EACH_PTR(bb->parents, parent) {
dmrC_remove_bb_from_list(&parent->children, bb, 0);
} END_FOR_EACH_PTR(parent);
bb->parents = NULL;
}
void dmrC_kill_unreachable_bbs(struct dmr_C *C, struct entrypoint *ep)
{
struct basic_block *bb;
unsigned long generation = ++C->L->bb_generation;
mark_bb_reachable(ep->entry->bb, generation);
FOR_EACH_PTR(ep->bbs, bb) {
if (bb->generation == generation)
continue;
/* Mark it as being dead */
dmrC_kill_bb(C, bb);
bb->ep = NULL;
DELETE_CURRENT_PTR(bb);
} END_FOR_EACH_PTR(bb);
ptrlist_pack((struct ptr_list **) &ep->bbs);
}
static int rewrite_parent_branch(struct dmr_C *C, struct basic_block *bb, struct basic_block *old, struct basic_block *new)
{

@ -15,10 +15,6 @@ extern "C" {
#endif
#define REPEAT_CSE 1
#define REPEAT_SYMBOL_CLEANUP 2
#define REPEAT_CFG_CLEANUP 3
struct entrypoint;
struct instruction;
@ -28,34 +24,17 @@ extern void dmrC_simplify_symbol_usage(struct dmr_C *C, struct entrypoint *ep);
extern void dmrC_simplify_memops(struct dmr_C *C, struct entrypoint *ep);
extern void dmrC_pack_basic_blocks(struct dmr_C *C, struct entrypoint *ep);
extern void dmrC_convert_instruction_target(struct dmr_C *C, struct instruction *insn, pseudo_t src);
extern void dmrC_cleanup_and_cse(struct dmr_C *C, struct entrypoint *ep);
extern int dmrC_simplify_instruction(struct dmr_C *C, struct instruction *);
extern void dmrC_kill_bb(struct dmr_C *C, struct basic_block *);
extern void dmrC_kill_use(struct dmr_C *C, pseudo_t *usep);
extern void dmrC_remove_use(struct dmr_C *C, pseudo_t *);
extern void dmrC_kill_insn(struct dmr_C *C, struct instruction *, int force);
static inline void dmrC_kill_instruction(struct dmr_C *C, struct instruction *insn)
{
dmrC_kill_insn(C, insn, 0);
}
static inline void dmrC_kill_instruction_force(struct dmr_C *C, struct instruction *insn)
{
dmrC_kill_insn(C, insn, 1);
}
extern void dmrC_kill_unreachable_bbs(struct dmr_C *C, struct entrypoint *ep);
void dmrC_check_access(struct dmr_C *C, struct instruction *insn);
void dmrC_convert_load_instruction(struct dmr_C *C, struct instruction *, pseudo_t);
void dmrC_rewrite_load_instruction(struct dmr_C *C, struct instruction *, struct pseudo_list *);
int dmrC_dominates(struct dmr_C *C, pseudo_t pseudo, struct instruction *insn, struct instruction *dom, int local);
extern void dmrC_clear_liveness(struct entrypoint *ep);
extern void dmrC_track_pseudo_liveness(struct dmr_C *C, struct entrypoint *ep);
extern void dmrC_track_pseudo_death(struct dmr_C *C, struct entrypoint *ep);
extern void dmrC_track_phi_uses(struct dmr_C *C, struct instruction *insn);
extern void dmrC_vrfy_flow(struct entrypoint *ep);
extern int dmrC_pseudo_in_list(struct pseudo_list *list, pseudo_t pseudo);

@ -16,7 +16,9 @@
#include <parse.h>
#include <expression.h>
#include <linearize.h>
#if 0
#include <flow.h>
#endif
#include <target.h>
static pseudo_t linearize_statement(struct dmr_C *C, struct entrypoint *ep, struct statement *stmt);
@ -823,6 +825,20 @@ static pseudo_t symbol_pseudo(struct dmr_C *C, struct entrypoint *ep, struct sym
return pseudo;
}
unsigned int dmrC_value_size(long long value)
{
value >>= 8;
if (!value)
return 8;
value >>= 8;
if (!value)
return 16;
value >>= 16;
if (!value)
return 32;
return 64;
}
pseudo_t dmrC_value_pseudo(struct dmr_C *C, struct symbol *type, long long val)
{
int hash = val & (MAX_VAL_HASH-1);
@ -2304,6 +2320,7 @@ static struct entrypoint *linearize_fn(struct dmr_C *C, struct symbol *sym, stru
*/
dmrC_kill_unreachable_bbs(C, ep);
#if 0
if (C->optimize) {
if (show_details) {
@ -2377,6 +2394,7 @@ static struct entrypoint *linearize_fn(struct dmr_C *C, struct symbol *sym, stru
goto repeat;
}
}
#endif
/* Finally, add deathnotes to pseudos now that we have them */
if (C->dbg_dead)
@ -2402,6 +2420,264 @@ struct entrypoint *dmrC_linearize_symbol(struct dmr_C *C, struct symbol *sym)
return NULL;
}
static void mark_bb_reachable(struct basic_block *bb, unsigned long generation)
{
struct basic_block *child;
if (bb->generation == generation)
return;
bb->generation = generation;
FOR_EACH_PTR(bb->children, child) {
mark_bb_reachable(child, generation);
} END_FOR_EACH_PTR(child);
}
void dmrC_kill_unreachable_bbs(struct dmr_C *C, struct entrypoint *ep)
{
struct basic_block *bb;
unsigned long generation = ++C->L->bb_generation;
mark_bb_reachable(ep->entry->bb, generation);
FOR_EACH_PTR(ep->bbs, bb) {
if (bb->generation == generation)
continue;
/* Mark it as being dead */
dmrC_kill_bb(C, bb);
bb->ep = NULL;
DELETE_CURRENT_PTR(bb);
} END_FOR_EACH_PTR(bb);
ptrlist_pack((struct ptr_list **) &ep->bbs);
}
static int delete_pseudo_user_list_entry(struct dmr_C *C, struct pseudo_user_list **list, pseudo_t *entry, int count)
{
struct pseudo_user *pu;
FOR_EACH_PTR(*list, pu) {
if (pu->userp == entry) {
MARK_CURRENT_DELETED(struct pseudo_user *, pu);
if (!--count)
goto out;
}
} END_FOR_EACH_PTR(pu);
assert(count <= 0);
out:
if (ptrlist_size((struct ptr_list *)*list) == 0)
*list = NULL;
return count;
}
static inline void remove_usage(struct dmr_C *C, pseudo_t p, pseudo_t *usep)
{
if (dmrC_has_use_list(p)) {
delete_pseudo_user_list_entry(C, &p->users, usep, 1);
if (!p->users)
dmrC_kill_instruction(C, p->def);
}
}
static inline void concat_user_list(struct pseudo_user_list *src, struct pseudo_user_list **dst)
{
ptrlist_concat((struct ptr_list *)src, (struct ptr_list **)dst);
}
void dmrC_convert_instruction_target(struct dmr_C *C, struct instruction *insn, pseudo_t src)
{
pseudo_t target;
struct pseudo_user *pu;
/*
* Go through the "insn->users" list and replace them all..
*/
target = insn->target;
if (target == src)
return;
FOR_EACH_PTR(target->users, pu) {
if (*pu->userp != VOID_PSEUDO(C)) {
assert(*pu->userp == target);
*pu->userp = src;
}
} END_FOR_EACH_PTR(pu);
if (dmrC_has_use_list(src))
concat_user_list(target->users, &src->users);
target->users = NULL;
}
static void kill_defs(struct dmr_C *C, struct instruction *insn)
{
pseudo_t target = insn->target;
if (!dmrC_has_use_list(target))
return;
if (target->def != insn)
return;
dmrC_convert_instruction_target(C, insn, VOID_PSEUDO(C));
}
void dmrC_kill_bb(struct dmr_C *C, struct basic_block *bb)
{
struct instruction *insn;
struct basic_block *child, *parent;
FOR_EACH_PTR(bb->insns, insn) {
dmrC_kill_instruction_force(C, insn);
kill_defs(C, insn);
/*
* We kill unreachable instructions even if they
* otherwise aren't "killable" (e.g. volatile loads)
*/
} END_FOR_EACH_PTR(insn);
bb->insns = NULL;
FOR_EACH_PTR(bb->children, child) {
dmrC_remove_bb_from_list(&child->parents, bb, 0);
} END_FOR_EACH_PTR(child);
bb->children = NULL;
FOR_EACH_PTR(bb->parents, parent) {
dmrC_remove_bb_from_list(&parent->children, bb, 0);
} END_FOR_EACH_PTR(parent);
bb->parents = NULL;
}
void dmrC_kill_use(struct dmr_C *C, pseudo_t *usep)
{
if (usep) {
pseudo_t p = *usep;
*usep = VOID_PSEUDO(C);
remove_usage(C, p, usep);
}
}
static void kill_use_list(struct dmr_C *C, struct pseudo_list *list)
{
pseudo_t p;
FOR_EACH_PTR(list, p) {
if (p == VOID_PSEUDO(C))
continue;
dmrC_kill_use(C, THIS_ADDRESS(pseudo_t, p));
} END_FOR_EACH_PTR(p);
}
/*
* kill an instruction:
* - remove it from its bb
* - remove the usage of all its operands
* If forse is zero, the normal case, the function only for
* instructions free of (possible) side-effects. Otherwise
* the function does that unconditionally (must only be used
* for unreachable instructions.
*/
void dmrC_kill_insn(struct dmr_C *C, struct instruction *insn, int force)
{
if (!insn || !insn->bb)
return;
switch (insn->opcode) {
case OP_SEL:
case OP_RANGE:
dmrC_kill_use(C, &insn->src3);
/* fall through */
case OP_ADD:
case OP_SUB:
case OP_MULU:
case OP_MULS:
case OP_DIVU:
case OP_DIVS:
case OP_MODU:
case OP_MODS:
case OP_SHL:
case OP_LSR:
case OP_ASR:
/* Logical */
case OP_AND:
case OP_OR:
case OP_XOR:
case OP_AND_BOOL:
case OP_OR_BOOL:
case OP_SET_EQ:
case OP_SET_NE:
case OP_SET_LE:
case OP_SET_GE:
case OP_SET_LT:
case OP_SET_GT:
case OP_SET_B:
case OP_SET_A:
case OP_SET_BE:
case OP_SET_AE:
dmrC_kill_use(C, &insn->src2);
/* fall through */
case OP_CAST:
case OP_SCAST:
case OP_FPCAST:
case OP_PTRCAST:
case OP_SETVAL:
case OP_NOT: case OP_NEG:
case OP_SLICE:
dmrC_kill_use(C, &insn->src1);
break;
case OP_PHI:
kill_use_list(C, insn->phi_list);
break;
case OP_PHISOURCE:
dmrC_kill_use(C, &insn->phi_src);
break;
case OP_SYMADDR:
C->L->repeat_phase |= REPEAT_SYMBOL_CLEANUP;
break;
case OP_CBR:
/* fall through */
case OP_COMPUTEDGOTO:
dmrC_kill_use(C, &insn->cond);
break;
case OP_CALL:
if (!force) {
/* a "pure" function can be killed too */
if (!(insn->func->type == PSEUDO_SYM))
return;
if (!(insn->func->sym->ctype.modifiers & MOD_PURE))
return;
}
kill_use_list(C, insn->arguments);
if (insn->func->type == PSEUDO_REG)
dmrC_kill_use(C, &insn->func);
break;
case OP_LOAD:
if (!force && insn->type->ctype.modifiers & MOD_VOLATILE)
return;
dmrC_kill_use(C, &insn->src);
break;
case OP_STORE:
if (!force)
return;
dmrC_kill_use(C, &insn->src);
dmrC_kill_use(C, &insn->target);
break;
case OP_ENTRY:
/* ignore */
return;
case OP_BR:
default:
break;
}
insn->bb = NULL;
C->L->repeat_phase |= REPEAT_CSE;
return;
}
void dmrC_init_linearizer(struct dmr_C *C) {
struct linearizer_state_t *L = (struct linearizer_state_t *)calloc(1, sizeof(struct linearizer_state_t));

@ -467,11 +467,36 @@ const char *dmrC_show_pseudo(struct dmr_C *C, pseudo_t pseudo);
void dmrC_show_bb(struct dmr_C *C, struct basic_block *bb);
const char *dmrC_show_instruction(struct dmr_C *C, struct instruction *insn);
void dmrC_convert_instruction_target(struct dmr_C *C, struct instruction *insn, pseudo_t src);
void dmrC_kill_use(struct dmr_C *C, pseudo_t *usep);
void dmrC_kill_insn(struct dmr_C *C, struct instruction *, int force);
void dmrC_kill_unreachable_bbs(struct dmr_C *C, struct entrypoint *ep);
void dmrC_kill_bb(struct dmr_C *C, struct basic_block *);
static inline void dmrC_kill_instruction(struct dmr_C *C, struct instruction *insn)
{
dmrC_kill_insn(C, insn, 0);
}
static inline void dmrC_kill_instruction_force(struct dmr_C *C, struct instruction *insn)
{
dmrC_kill_insn(C, insn, 1);
}
void dmrC_clear_liveness(struct entrypoint *ep);
void dmrC_track_pseudo_liveness(struct dmr_C *C, struct entrypoint *ep);
void dmrC_track_pseudo_death(struct dmr_C *C, struct entrypoint *ep);
void dmrC_track_phi_uses(struct dmr_C *C, struct instruction *insn);
void dmrC_init_linearizer(struct dmr_C *C);
void dmrC_destroy_linearizer(struct dmr_C *C);
#define dmrC_hashval(x) ((unsigned long)(((uintptr_t)(x))))
#define REPEAT_CSE 1
#define REPEAT_SYMBOL_CLEANUP 2
#define REPEAT_CFG_CLEANUP 3
#ifdef __cplusplus
}
#endif

@ -11,7 +11,7 @@
#include <parse.h>
#include <expression.h>
#include <linearize.h>
#include <flow.h>
//#include <flow.h>
static void phi_defines(struct dmr_C *C, struct instruction * phi_node, pseudo_t target,
void (*defines)(struct dmr_C *C, struct basic_block *, pseudo_t))

@ -194,15 +194,6 @@ static inline void remove_usage(struct dmr_C *C, pseudo_t p, pseudo_t *usep)
}
}
void dmrC_kill_use(struct dmr_C *C, pseudo_t *usep)
{
if (usep) {
pseudo_t p = *usep;
*usep = VOID_PSEUDO(C);
remove_usage(C, p, usep);
}
}
// From Luc: sssa-mini
/*
* Like kill_use() but do not recursively kill instructions
@ -227,125 +218,6 @@ static void kill_use_list(struct dmr_C *C, struct pseudo_list *list)
} END_FOR_EACH_PTR(p);
}
/*
* kill an instruction:
* - remove it from its bb
* - remove the usage of all its operands
* If forse is zero, the normal case, the function only for
* instructions free of (possible) side-effects. Otherwise
* the function does that unconditionally (must only be used
* for unreachable instructions.
*/
void dmrC_kill_insn(struct dmr_C *C, struct instruction *insn, int force)
{
if (!insn || !insn->bb)
return;
switch (insn->opcode) {
case OP_SEL:
case OP_RANGE:
dmrC_kill_use(C, &insn->src3);
/* fall through */
case OP_ADD:
case OP_SUB:
case OP_MULU:
case OP_MULS:
case OP_DIVU:
case OP_DIVS:
case OP_MODU:
case OP_MODS:
case OP_SHL:
case OP_LSR:
case OP_ASR:
/* Logical */
case OP_AND:
case OP_OR:
case OP_XOR:
case OP_AND_BOOL:
case OP_OR_BOOL:
case OP_SET_EQ:
case OP_SET_NE:
case OP_SET_LE:
case OP_SET_GE:
case OP_SET_LT:
case OP_SET_GT:
case OP_SET_B:
case OP_SET_A:
case OP_SET_BE:
case OP_SET_AE:
dmrC_kill_use(C, &insn->src2);
/* fall through */
case OP_CAST:
case OP_SCAST:
case OP_FPCAST:
case OP_PTRCAST:
case OP_SETVAL:
case OP_NOT: case OP_NEG:
case OP_SLICE:
dmrC_kill_use(C, &insn->src1);
break;
case OP_PHI:
kill_use_list(C, insn->phi_list);
break;
case OP_PHISOURCE:
dmrC_kill_use(C, &insn->phi_src);
break;
case OP_SYMADDR:
C->L->repeat_phase |= REPEAT_SYMBOL_CLEANUP;
break;
case OP_CBR:
/* fall through */
case OP_COMPUTEDGOTO:
dmrC_kill_use(C, &insn->cond);
break;
case OP_CALL:
if (!force) {
/* a "pure" function can be killed too */
if (!(insn->func->type == PSEUDO_SYM))
return;
if (!(insn->func->sym->ctype.modifiers & MOD_PURE))
return;
}
kill_use_list(C, insn->arguments);
if (insn->func->type == PSEUDO_REG)
dmrC_kill_use(C, &insn->func);
break;
case OP_LOAD:
if (!force && insn->type->ctype.modifiers & MOD_VOLATILE)
return;
dmrC_kill_use(C, &insn->src);
break;
case OP_STORE:
if (!force)
return;
dmrC_kill_use(C, &insn->src);
dmrC_kill_use(C, &insn->target);
break;
case OP_ENTRY:
/* ignore */
return;
case OP_BR:
default:
break;
}
insn->bb = NULL;
C->L->repeat_phase |= REPEAT_CSE;
return;
}
/*
* Kill trivially dead instructions
*/
@ -424,20 +296,6 @@ static int replace_with_pseudo(struct dmr_C *C, struct instruction *insn, pseudo
return REPEAT_CSE;
}
unsigned int dmrC_value_size(long long value)
{
value >>= 8;
if (!value)
return 8;
value >>= 8;
if (!value)
return 16;
value >>= 16;
if (!value)
return 32;
return 64;
}
/*
* Try to determine the maximum size of bits in a pseudo.
*

Loading…
Cancel
Save