From 65112ceec0cb92ec853f3391263d51a12b15bad0 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 27 Aug 2018 11:41:48 -0700 Subject: Improve getFallthrough (#1643) That method looks through tee_locals and other operations that receive a value and let it flow through them, like a block's final value, etc. It just handled a few such operations, with this PR all of them should be handled. Also refactor it out of the OptimizeInstructions pass as I think it may be useful for propagating returned constants. --- src/ir/properties.h | 36 ++++++++++++++++++++++++++++++++++++ src/passes/OptimizeInstructions.cpp | 20 ++------------------ 2 files changed, 38 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/ir/properties.h b/src/ir/properties.h index 7cbbe73f0..6848e9481 100644 --- a/src/ir/properties.h +++ b/src/ir/properties.h @@ -146,6 +146,42 @@ inline Index getZeroExtBits(Expression* curr) { return Bits::getMaskedBits(curr->cast()->right->cast()->value.geti32()); } +// Returns a falling-through value, that is, it looks through a tee_local +// and other operations that receive a value and let it flow through them. +inline Expression* getFallthrough(Expression* curr) { + // If the current node is unreachable, there is no value + // falling through. + if (curr->type == unreachable) { + return curr; + } + if (auto* set = curr->dynCast()) { + if (set->isTee()) { + return getFallthrough(set->value); + } + } else if (auto* block = curr->dynCast()) { + // if no name, we can't be broken to, and then can look at the fallthrough + if (!block->name.is() && block->list.size() > 0) { + return getFallthrough(block->list.back()); + } + } else if (auto* loop = curr->dynCast()) { + return getFallthrough(loop->body); + } else if (auto* iff = curr->dynCast()) { + if (iff->ifFalse) { + // Perhaps just one of the two actually returns. + if (iff->ifTrue->type == unreachable) { + return getFallthrough(iff->ifFalse); + } else if (iff->ifFalse->type == unreachable) { + return getFallthrough(iff->ifTrue); + } + } + } else if (auto* br = curr->dynCast()) { + if (br->condition && br->value) { + return getFallthrough(br->value); + } + } + return curr; +} + } // Properties } // wasm diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index 55042d96f..73f78611b 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -258,22 +258,6 @@ Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider) { } } -// looks through fallthrough operations, like tee_local, block fallthrough, etc. -// too and block fallthroughs, etc. -Expression* getFallthrough(Expression* curr) { - if (auto* set = curr->dynCast()) { - if (set->isTee()) { - return getFallthrough(set->value); - } - } else if (auto* block = curr->dynCast()) { - // if no name, we can't be broken to, and then can look at the fallthrough - if (!block->name.is() && block->list.size() > 0) { - return getFallthrough(block->list.back()); - } - } - return curr; -} - // Useful information about locals struct LocalInfo { static const Index kUnknown = Index(-1); @@ -316,7 +300,7 @@ struct LocalScanner : PostWalker { auto type = getFunction()->getLocalType(curr->index); if (type != i32 && type != i64) return; // an integer var, worth processing - auto* value = getFallthrough(curr->value); + auto* value = Properties::getFallthrough(curr->value); auto& info = localInfo[curr->index]; info.maxBits = std::max(info.maxBits, getMaxBits(value, this)); auto signExtBits = LocalInfo::kUnknown; @@ -421,7 +405,7 @@ struct OptimizeInstructions : public WalkerPassdynCast()) { + if (auto* load = Properties::getFallthrough(ext)->dynCast()) { // pattern match a load of 8 bits and a sign extend using a shl of 24 then shr_s of 24 as well, etc. if (LoadUtils::canBeSigned(load) && ((load->bytes == 1 && bits == 8) || (load->bytes == 2 && bits == 16))) { -- cgit v1.2.3