diff options
| author | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2018-03-15 20:04:25 +0100 |
|---|---|---|
| committer | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2018-06-30 23:29:28 +0200 |
| commit | 6ad43a13c2e2b556bdd697a2c47b449cbaa80262 (patch) | |
| tree | 4c15cc74cba85db266727ace74acb9bc9b562267 | |
| parent | 4723d27700f35d172053c725488a84ffdac9891f (diff) | |
| download | sparse-dev-6ad43a13c2e2b556bdd697a2c47b449cbaa80262.tar.gz | |
kds: shortcut for kill_dead_stores()
In kill_dead_stores(), instructions must be scanned backward
in order to check if the store is dead and can be removed.
However, if the corresponding pseudo has a single user,
this user is a store and the it correspond to a local symbol,
then it's not needed to scan, the store can be directly be removed.
This is somehow important for some semi-pathological case where
some BB contains a lot of dead stores because the current way is
annoyingly O(n^2).
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
| -rw-r--r-- | flow.c | 27 |
1 files changed, 27 insertions, 0 deletions
@@ -766,11 +766,38 @@ void simplify_symbol_usage(struct entrypoint *ep) } END_FOR_EACH_PTR(pseudo); } +static struct pseudo_user *first_user(pseudo_t p) +{ + struct pseudo_user *pu; + FOR_EACH_PTR(p->users, pu) { + if (!pu) + continue; + return pu; + } END_FOR_EACH_PTR(pu); + return NULL; +} + void kill_dead_stores(struct entrypoint *ep, pseudo_t addr, int local) { unsigned long generation; struct basic_block *bb; + switch (pseudo_user_list_size(addr->users)) { + case 0: + return; + case 1: + if (local) { + struct pseudo_user *pu = first_user(addr); + struct instruction *insn = pu->insn; + if (insn->opcode == OP_STORE) { + kill_instruction_force(insn); + return; + } + } + default: + break; + } + generation = ++bb_generation; FOR_EACH_PTR(ep->bbs, bb) { if (bb->children) |
