From 57432d59960486fbab31753eb6ac295b2304fa86 Mon Sep 17 00:00:00 2001 From: Ben Vanik Date: Sat, 7 Dec 2013 04:57:37 -0800 Subject: [PATCH] Making ContextPromotion actually remove dead stores. --- .../compiler/passes/context_promotion_pass.cc | 41 +++++++++++++++---- .../compiler/passes/context_promotion_pass.h | 1 + 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/src/alloy/compiler/passes/context_promotion_pass.cc b/src/alloy/compiler/passes/context_promotion_pass.cc index dffe465f1..6d9e062f1 100644 --- a/src/alloy/compiler/passes/context_promotion_pass.cc +++ b/src/alloy/compiler/passes/context_promotion_pass.cc @@ -60,6 +60,7 @@ int ContextPromotionPass::Run(FunctionBuilder* builder) { // This is more generally done by DSE, however if it could be done here // instead as it may be faster (at least on the block-level). + // Promote loads to values. // Process each block independently, for now. Block* block = builder->first_block(); while (block) { @@ -67,6 +68,13 @@ int ContextPromotionPass::Run(FunctionBuilder* builder) { block = block->next; } + // Remove all dead stores. + block = builder->first_block(); + while (block) { + RemoveDeadStoresBlock(block); + block = block->next; + } + return 0; } @@ -92,14 +100,6 @@ void ContextPromotionPass::PromoteBlock(Block* block) { } else if (i->opcode == &OPCODE_STORE_CONTEXT_info) { size_t offset = i->src1.offset; Value* value = i->src2.value; - Value* previous_value = context_values_[offset]; - if (previous_value && - previous_value->def && - previous_value->def->opcode == &OPCODE_STORE_CONTEXT_info) { - // Legit previous value from a useless store. - // Remove the store entirely. - previous_value->def->Remove(); - } // Store value into the table for later. context_values_[offset] = value; } @@ -107,3 +107,28 @@ void ContextPromotionPass::PromoteBlock(Block* block) { i = i->next; } } + +void ContextPromotionPass::RemoveDeadStoresBlock(Block* block) { + // TODO(benvanik): use a bitvector. + // To avoid clearing the structure, we use a token. + Value* token = (Value*)block; + + // Walk backwards and mark offsets that are written to. + // If the offset was written to earlier, ignore the store. + Instr* i = block->instr_tail; + while (i) { + Instr* prev = i->prev; + if (i->opcode == &OPCODE_STORE_CONTEXT_info) { + size_t offset = i->src1.offset; + Value* value = i->src2.value; + if (context_values_[offset] != token) { + // Mark offset as written to. + context_values_[offset] = token; + } else { + // Already written to. Remove this store. + i->Remove(); + } + } + i = prev; + } +} diff --git a/src/alloy/compiler/passes/context_promotion_pass.h b/src/alloy/compiler/passes/context_promotion_pass.h index 4a8211246..f4d7226ee 100644 --- a/src/alloy/compiler/passes/context_promotion_pass.h +++ b/src/alloy/compiler/passes/context_promotion_pass.h @@ -29,6 +29,7 @@ public: private: void PromoteBlock(hir::Block* block); + void RemoveDeadStoresBlock(hir::Block* block); private: size_t context_values_size_;