diff options
| -rw-r--r-- | Makefile | 3 | ||||
| -rw-r--r-- | flow.h | 2 | ||||
| -rw-r--r-- | linearize.c | 3 | ||||
| -rw-r--r-- | linearize.h | 2 | ||||
| -rw-r--r-- | register.c | 155 |
5 files changed, 164 insertions, 1 deletions
@@ -16,7 +16,7 @@ LIB_H= token.h parse.h lib.h symbol.h scope.h expression.h target.h \ LIB_OBJS= target.o parse.o tokenize.o pre-process.o symbol.o lib.o scope.o \ expression.o show-parse.o evaluate.o expand.o inline.o linearize.o \ - sort.o flow.o cse.o simplify.o compat-$(OS).o + sort.o flow.o cse.o simplify.o register.o compat-$(OS).o LIB_FILE= sparse.a LIBS=$(LIB_FILE) @@ -77,6 +77,7 @@ linearize.o: $(LIB_H) flow.o: $(LIB_H) cse.o: $(LIB_H) simplify.o: $(LIB_H) +register.o: $(LIB_H) sort.o: $(LIB_H) inline.o: $(LIB_H) target.o: $(LIB_H) @@ -18,4 +18,6 @@ extern void kill_bb(struct basic_block *); extern void kill_use(pseudo_t *); extern void kill_instruction(struct instruction *); +extern void track_pseudo_usage(struct entrypoint *ep); + #endif diff --git a/linearize.c b/linearize.c index 9fe911d8..62ae8f35 100644 --- a/linearize.c +++ b/linearize.c @@ -1770,6 +1770,9 @@ static struct entrypoint *linearize_fn(struct symbol *sym, struct symbol *base_t /* Cleanup */ clear_symbol_pseudos(ep); + /* And track pseudo register usage */ + track_pseudo_usage(ep); + return ep; } diff --git a/linearize.h b/linearize.h index 524c2099..13733963 100644 --- a/linearize.h +++ b/linearize.h @@ -23,6 +23,7 @@ struct pseudo { unsigned int usage:24, type:8; struct pseudo_ptr_list *users; + struct instruction_list *insns; union { struct symbol *sym; struct instruction *def; @@ -244,6 +245,7 @@ struct entrypoint { struct basic_block_list *bbs; struct basic_block *active; struct basic_block *entry; + struct pseudo_list *pseudos; }; extern void insert_select(struct basic_block *bb, struct instruction *br, struct instruction *phi, pseudo_t true, pseudo_t false); diff --git a/register.c b/register.c new file mode 100644 index 00000000..de902713 --- /dev/null +++ b/register.c @@ -0,0 +1,155 @@ +/* + * Register - track pseudo usage, maybe eventually try to do register + * allocation. + * + * Copyright (C) 2004 Linus Torvalds + */ + +#include <assert.h> + +#include "parse.h" +#include "expression.h" +#include "linearize.h" +#include "flow.h" + +static inline int trackable_pseudo(pseudo_t pseudo) +{ + return pseudo && (pseudo->type == PSEUDO_REG || pseudo->type == PSEUDO_PHI); +} + +static void insn_uses(struct entrypoint *ep, struct instruction *insn, pseudo_t pseudo) +{ + if (trackable_pseudo(pseudo)) { + struct instruction *def = pseudo->def; +#if 1 + /* + * This assert is wrong, since this actually _can_ happen for + * truly undefined programs, but it's good for finding bugs. + */ + assert(def && def->bb); +#else + if (!def || !def->bb) + warning(insn->bb->pos, "undef pseudo ;("); +#endif + add_instruction(&pseudo->insns, insn); + } +} + +static void insn_defines(struct entrypoint *ep, struct instruction *insn, pseudo_t pseudo) +{ + assert(trackable_pseudo(pseudo)); + add_pseudo(&ep->pseudos, pseudo); +} + +static void track_instruction_usage(struct entrypoint *ep, struct instruction *insn) +{ + pseudo_t pseudo; + + #define USES(x) insn_uses(ep, insn, insn->x) + #define DEFINES(x) insn_defines(ep, insn, insn->x) + + switch (insn->opcode) { + case OP_RET: + USES(src); + break; + + case OP_BR: case OP_SWITCH: + USES(cond); + break; + + case OP_COMPUTEDGOTO: + USES(target); + + /* Binary */ + case OP_BINARY ... OP_BINARY_END: + case OP_BINCMP ... OP_BINCMP_END: + USES(src1); USES(src2); DEFINES(target); + break; + + /* Uni */ + case OP_NOT: case OP_NEG: + USES(src1); DEFINES(target); + break; + + /* Setcc - always in combination with a select or conditional branch */ + case OP_SETCC: + USES(src); + break; + + case OP_SEL: + USES(src1); USES(src2); DEFINES(target); + break; + + /* Memory */ + case OP_LOAD: + USES(src); DEFINES(target); + break; + + case OP_STORE: + USES(src); USES(target); + break; + + case OP_SETVAL: + USES(symbol); DEFINES(target); + break; + + /* Other */ + case OP_PHI: + DEFINES(target); + FOR_EACH_PTR(insn->phi_list, pseudo) { + insn_uses(ep, insn, pseudo); + } END_FOR_EACH_PTR(pseudo); + break; + + case OP_PHISOURCE: + USES(src1); DEFINES(target); + break; + + case OP_CAST: + USES(src); DEFINES(target); + break; + + case OP_CALL: + USES(func); + if (insn->target != VOID) + DEFINES(target); + FOR_EACH_PTR(insn->arguments, pseudo) { + insn_uses(ep, insn, pseudo); + } END_FOR_EACH_PTR(pseudo); + break; + + case OP_SLICE: + USES(base); DEFINES(target); + break; + + case OP_BADOP: + case OP_INVOKE: + case OP_UNWIND: + case OP_MALLOC: + case OP_FREE: + case OP_ALLOCA: + case OP_GET_ELEMENT_PTR: + case OP_VANEXT: + case OP_VAARG: + case OP_SNOP: + case OP_LNOP: + case OP_NOP: + case OP_CONTEXT: + break; + } +} + +void track_pseudo_usage(struct entrypoint *ep) +{ + struct basic_block *bb; + + FOR_EACH_PTR(ep->bbs, bb) { + struct instruction *insn; + FOR_EACH_PTR(bb->insns, insn) { + if (!insn->bb) + continue; + assert(insn->bb == bb); + track_instruction_usage(ep, insn); + } END_FOR_EACH_PTR(insn); + } END_FOR_EACH_PTR(bb); +} |
