diff options
| author | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2017-01-10 10:24:46 +0100 |
|---|---|---|
| committer | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2018-08-26 01:14:15 +0200 |
| commit | 2be8fdea5dc4160898bc820e05f65c6f1cd149cb (patch) | |
| tree | 5148c165602cc9940255f98874607d12b7364d14 | |
| parent | 9dd1abf2b98f678dba616ddbf587666a14367b9a (diff) | |
| download | sparse-dev-2be8fdea5dc4160898bc820e05f65c6f1cd149cb.tar.gz | |
add a function to remove deadborn instructions
The values produced by expressions are not always used,
it's normal. However this produce useless code that will
need to be removed, sooner or later.
Currently, this removal of dead instructions is done as
part of the normal instruction simplification where each
kind of instruction are checked if it is used or not and,
if not, the usage is removed from the operands and the
instruction itself is removed. This has several drawbacks:
* this is done at each simplification cycle while it is
only needed just after linearization
* there is a large overlap between what is needed to correctly
remove these dead instructions and kill_instruction()
* instructions which are not simplified are forgotten
for this and thus never removed.
Change this by adding a separate function to remove these
deadborn instructions.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
| -rw-r--r-- | flow.h | 1 | ||||
| -rw-r--r-- | simplify.c | 22 |
2 files changed, 23 insertions, 0 deletions
@@ -20,6 +20,7 @@ extern void simplify_memops(struct entrypoint *ep); extern void pack_basic_blocks(struct entrypoint *ep); extern void convert_instruction_target(struct instruction *insn, pseudo_t src); +extern void remove_dead_insns(struct entrypoint *); extern int simplify_instruction(struct instruction *); extern void kill_bb(struct basic_block *); @@ -369,6 +369,28 @@ static int dead_insn(struct instruction *insn, pseudo_t *src1, pseudo_t *src2, p return REPEAT_CSE; } +static inline bool has_target(struct instruction *insn) +{ + return opcode_table[insn->opcode].flags & OPF_TARGET; +} + +void remove_dead_insns(struct entrypoint *ep) +{ + struct basic_block *bb; + + FOR_EACH_PTR_REVERSE(ep->bbs, bb) { + struct instruction *insn; + FOR_EACH_PTR_REVERSE(bb->insns, insn) { + if (!insn->bb) + continue; + if (!has_target(insn)) + continue; + if (!has_users(insn->target)) + kill_instruction(insn); + } END_FOR_EACH_PTR_REVERSE(insn); + } END_FOR_EACH_PTR_REVERSE(bb); +} + static inline int constant(pseudo_t pseudo) { return pseudo->type == PSEUDO_VAL; |
