diff --git a/src/relooper/Relooper.cpp b/src/relooper/Relooper.cpp index 65d4eca0bbb4d..e91c6e748cd22 100644 --- a/src/relooper/Relooper.cpp +++ b/src/relooper/Relooper.cpp @@ -893,10 +893,22 @@ void Relooper::Calculate(Block *Entry) { func(Loop->Next); \ } + // Find the single block that must be hit in a shape, or NULL if there is more than one + Block *FollowNaturalFlow(Shape *S) { + SHAPE_SWITCH(S, { + return Simple->Inner; + }, { + return NULL; + }, { + return FollowNaturalFlow(Loop->Inner); + }); + } + // Remove unneeded breaks and continues. // A flow operation is trivially unneeded if the shape we naturally get to by normal code // execution is the same as the flow forces us to. void RemoveUnneededFlows(Shape *Root, Shape *Natural=NULL) { + Block *NaturalBlock = FollowNaturalFlow(Natural); Shape *Next = Root; while (Next) { Root = Next; @@ -911,7 +923,7 @@ void Relooper::Calculate(Block *Entry) { for (BlockBranchMap::iterator iter = Simple->Inner->ProcessedBranchesOut.begin(); iter != Simple->Inner->ProcessedBranchesOut.end(); iter++) { Block *Target = iter->first; Branch *Details = iter->second; - if (Details->Type != Branch::Direct && Target->Parent == Natural) { + if (Details->Type != Branch::Direct && Target == NaturalBlock) { // note: cannot handle split blocks Details->Type = Branch::Direct; if (MultipleShape *Multiple = Shape::IsMultiple(Details->Ancestor)) { Multiple->NeedLoop--; @@ -1026,19 +1038,34 @@ void Relooper::SetAsmJSMode(int On) { #if DEBUG // Debugging -void DebugDump(BlockSet &Blocks, const char *prefix) { +void Debugging::Dump(BlockSet &Blocks, const char *prefix) { if (prefix) printf("%s ", prefix); for (BlockSet::iterator iter = Blocks.begin(); iter != Blocks.end(); iter++) { - printf("%d:\n", (*iter)->Id); - for (BlockBranchMap::iterator iter2 = (*iter)->BranchesOut.begin(); iter2 != (*iter)->BranchesOut.end(); iter2++) { - printf(" OUT %d\n", iter2->first->Id); - } - for (BlockSet::iterator iter2 = (*iter)->BranchesIn.begin(); iter2 != (*iter)->BranchesIn.end(); iter2++) { - printf(" IN %d\n", (*iter2)->Id); + Block *Curr = *iter; + printf("%d:\n", Curr->Id); + for (BlockBranchMap::iterator iter2 = Curr->BranchesOut.begin(); iter2 != Curr->BranchesOut.end(); iter2++) { + Block *Other = iter2->first; + printf(" -> %d\n", Other->Id); + assert(Other->BranchesIn.find(Curr) != Other->BranchesIn.end()); } } } +void Debugging::Dump(Shape *S, const char *prefix) { + if (prefix) printf("%s ", prefix); + printf(" %d ", S->Id); + SHAPE_SWITCH(S, { + printf("<< Simple with block %d\n", Simple->Inner->Id); + }, { + printf("<< Multiple\n"); + for (BlockShapeMap::iterator iter = Multiple->InnerMap.begin(); iter != Multiple->InnerMap.end(); iter++) { + printf(" with entry %d\n", iter->first->Id); + } + }, { + printf("<< Loop\n"); + }); +} + static void PrintDebug(const char *Format, ...) { printf("// "); va_list Args; diff --git a/src/relooper/Relooper.h b/src/relooper/Relooper.h index 5eabe8273a7ed..34b6db08fdd77 100644 --- a/src/relooper/Relooper.h +++ b/src/relooper/Relooper.h @@ -211,6 +211,7 @@ typedef std::map BlockBlockSetMap; #if DEBUG struct Debugging { static void Dump(BlockSet &Blocks, const char *prefix=NULL); + static void Dump(Shape *S, const char *prefix=NULL); }; #endif diff --git a/src/relooper/test.txt b/src/relooper/test.txt index 2ff70e664ab85..84a8c9050eb3a 100644 --- a/src/relooper/test.txt +++ b/src/relooper/test.txt @@ -129,12 +129,9 @@ do { break; } } while(0); -do { - if (label == 33) { - // block C; - break; - } -} while(0); +if (label == 33) { + // block C; +} while(1) { // block E // block F diff --git a/src/relooper/test_debug.txt b/src/relooper/test_debug.txt index a6823d561ac69..d18ed875c6702 100644 --- a/src/relooper/test_debug.txt +++ b/src/relooper/test_debug.txt @@ -34,86 +34,72 @@ int main() { // Process() called // Process() running blocks : 1: - OUT 2 - OUT 4 + -> 2 + -> 4 2: - OUT 3 - OUT 4 - IN 1 + -> 3 + -> 4 3: - OUT 4 - IN 2 + -> 4 4: - IN 1 - IN 2 - IN 3 entries: 1: - OUT 2 - OUT 4 + -> 2 + -> 4 // creating simple block with block #1 // Solipsizing branches into 2 relevant to solipsize: 1: - OUT 2 - OUT 4 + -> 2 + -> 4 // eliminated branch from 1 // Solipsizing branches into 4 relevant to solipsize: 1: - OUT 4 + -> 4 // eliminated branch from 1 // Process() running blocks : 2: - OUT 3 - OUT 4 + -> 3 + -> 4 3: - OUT 4 - IN 2 + -> 4 4: - IN 2 - IN 3 entries: 2: - OUT 3 - OUT 4 + -> 3 + -> 4 4: - IN 2 - IN 3 // Investigated independent groups: group: 2: - OUT 3 - OUT 4 + -> 3 + -> 4 3: - OUT 4 - IN 2 + -> 4 // Independent groups: 1 // Handleable independent groups: 1 // creating multiple block with 1 inner groups // multiple group with entry 2: 2: - OUT 3 - OUT 4 + -> 3 + -> 4 3: - OUT 4 - IN 2 + -> 4 // Solipsizing branches into 4 relevant to solipsize: 2: - OUT 3 - OUT 4 + -> 3 + -> 4 3: - OUT 4 - IN 2 + -> 4 // eliminated branch from 2 // eliminated branch from 3 // Process() called // Process() running blocks : 2: - OUT 3 + -> 3 3: - IN 2 entries: 2: - OUT 3 + -> 3 // creating simple block with block #2 // Solipsizing branches into 3 relevant to solipsize: 2: - OUT 3 + -> 3 // eliminated branch from 2 // Process() running blocks : 3: diff --git a/tools/shared.py b/tools/shared.py index f9d93289a79c6..645dfbe951941 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -295,7 +295,7 @@ def check_node_version(): # we re-check sanity when the settings are changed) # We also re-check sanity and clear the cache when the version changes -EMSCRIPTEN_VERSION = '1.4.5' +EMSCRIPTEN_VERSION = '1.4.6' def generate_sanity(): return EMSCRIPTEN_VERSION + '|' + get_llvm_target()