aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
authorLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2018-03-15 20:04:25 +0100
committerLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2018-06-30 23:29:28 +0200
commit6ad43a13c2e2b556bdd697a2c47b449cbaa80262 (patch)
tree4c15cc74cba85db266727ace74acb9bc9b562267
parent4723d27700f35d172053c725488a84ffdac9891f (diff)
downloadsparse-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.c27
1 files changed, 27 insertions, 0 deletions
diff --git a/flow.c b/flow.c
index 36934e43..e2943c23 100644
--- a/flow.c
+++ b/flow.c
@@ -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)