From c69253378014ffc451adf916d017d8f21faae77c Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 25 Sep 2017 14:36:32 -0700 Subject: fix dce bug with not updating the parent when turning a node unreachable (#1198) --- src/ast/type-updating.h | 16 +++++++++++--- src/passes/DeadCodeElimination.cpp | 43 ++++++++++++++++++++------------------ 2 files changed, 36 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/ast/type-updating.h b/src/ast/type-updating.h index 3cf2f2afe..8063b3e59 100644 --- a/src/ast/type-updating.h +++ b/src/ast/type-updating.h @@ -75,10 +75,16 @@ struct TypeUpdater : public ExpressionStackWalker> Expression* replaceCurrent(Expression* expression) { auto* old = getCurrent(); + if (old == expression) return expression; WalkerPass>::replaceCurrent(expression); // also update the type updater typeUpdater.noteReplacement(old, expression); @@ -219,14 +220,17 @@ struct DeadCodeElimination : public WalkerPass> } static void scan(DeadCodeElimination* self, Expression** currp) { + auto* curr = *currp; if (!self->reachable) { - // convert to an unreachable. do this without UB, even though we have no destructors on AST nodes + // convert to an unreachable safely #define DELEGATE(CLASS_TO_VISIT) { \ - self->typeUpdater.noteRecursiveRemoval(*currp); \ - ExpressionManipulator::convert(static_cast(*currp)); \ + auto* parent = self->typeUpdater.parents[curr]; \ + self->typeUpdater.noteRecursiveRemoval(curr); \ + ExpressionManipulator::convert(static_cast(curr)); \ + self->typeUpdater.noteAddition(curr, parent); \ break; \ } - switch ((*currp)->_id) { + switch (curr->_id) { case Expression::Id::BlockId: DELEGATE(Block); case Expression::Id::IfId: DELEGATE(If); case Expression::Id::LoopId: DELEGATE(Loop); @@ -256,7 +260,6 @@ struct DeadCodeElimination : public WalkerPass> #undef DELEGATE return; } - auto* curr =* currp; if (curr->is()) { self->pushTask(DeadCodeElimination::doVisitIf, currp); if (curr->cast()->ifFalse) { @@ -328,18 +331,18 @@ struct DeadCodeElimination : public WalkerPass> for (size_t i = 0; i < list.size(); ++i) { auto* elem = list[i]; if (isUnreachable(elem)) { - auto* replacement = elem; - if (i > 0) { - auto* block = getModule()->allocator.alloc(); - for (size_t j = 0; j < i; ++j) { - block->list.push_back(drop(list[j])); - } - block->list.push_back(list[i]); - block->finalize(type); - replacement = block; - } - replaceCurrent(replacement); - return; + auto* replacement = elem; + if (i > 0) { + auto* block = getModule()->allocator.alloc(); + for (size_t j = 0; j < i; ++j) { + block->list.push_back(drop(list[j])); + } + block->list.push_back(list[i]); + block->finalize(type); + replacement = block; + } + replaceCurrent(replacement); + return; } } } @@ -349,7 +352,7 @@ struct DeadCodeElimination : public WalkerPass> } void visitLoad(Load* curr) { - blockifyReachableOperands({ curr->ptr}, curr->type); + blockifyReachableOperands({ curr->ptr }, curr->type); } void visitStore(Store* curr) { @@ -369,11 +372,11 @@ struct DeadCodeElimination : public WalkerPass> } void visitBinary(Binary* curr) { - blockifyReachableOperands({ curr->left, curr->right}, curr->type); + blockifyReachableOperands({ curr->left, curr->right }, curr->type); } void visitSelect(Select* curr) { - blockifyReachableOperands({ curr->ifTrue, curr->ifFalse, curr->condition}, curr->type); + blockifyReachableOperands({ curr->ifTrue, curr->ifFalse, curr->condition }, curr->type); } void visitDrop(Drop* curr) { -- cgit v1.2.3