aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
authorLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2017-01-10 10:24:46 +0100
committerLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2018-08-26 01:14:15 +0200
commit2be8fdea5dc4160898bc820e05f65c6f1cd149cb (patch)
tree5148c165602cc9940255f98874607d12b7364d14
parent9dd1abf2b98f678dba616ddbf587666a14367b9a (diff)
downloadsparse-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.h1
-rw-r--r--simplify.c22
2 files changed, 23 insertions, 0 deletions
diff --git a/flow.h b/flow.h
index c8e12cf0..099767d4 100644
--- a/flow.h
+++ b/flow.h
@@ -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 *);
diff --git a/simplify.c b/simplify.c
index a786579e..76e94a11 100644
--- a/simplify.c
+++ b/simplify.c
@@ -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;