From 3634b45c63e420910c77a631352ab257b8a6039f Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sun, 11 Nov 2012 10:04:33 -0800 Subject: [PATCH 1/6] add relooper sources --- src/relooper/README.markdown | 14 + src/relooper/Relooper.cpp | 1038 ++++++++++++++++++++++++++++++ src/relooper/Relooper.h | 246 +++++++ src/relooper/doit.sh | 68 ++ src/relooper/emscripten/Makefile | 18 + src/relooper/emscripten/glue.js | 54 ++ src/relooper/emscripten/test.js | 44 ++ src/relooper/fuzzer.py | 116 ++++ src/relooper/ministring.h | 35 + src/relooper/paper.pdf | Bin 0 -> 220318 bytes src/relooper/test.cpp | 195 ++++++ src/relooper/test.txt | 99 +++ src/relooper/test2.c | 44 ++ src/relooper/test2.txt | 12 + src/relooper/test3.c | 42 ++ src/relooper/test3.txt | 27 + src/relooper/test4.cpp | 40 ++ src/relooper/test4.txt | 24 + src/relooper/test5.cpp | 40 ++ src/relooper/test5.txt | 32 + src/relooper/test6.cpp | 31 + src/relooper/test6.txt | 12 + src/relooper/test_dead.cpp | 28 + src/relooper/test_dead.txt | 9 + src/relooper/test_debug.cpp | 30 + src/relooper/test_debug.txt | 96 +++ src/relooper/test_fuzz1.cpp | 52 ++ src/relooper/test_fuzz1.txt | 44 ++ src/relooper/test_fuzz2.cpp | 34 + src/relooper/test_fuzz2.txt | 14 + src/relooper/test_fuzz3.cpp | 36 ++ src/relooper/test_fuzz3.txt | 9 + src/relooper/test_fuzz4.cpp | 38 ++ src/relooper/test_fuzz4.txt | 20 + src/relooper/test_fuzz5.cpp | 57 ++ src/relooper/test_fuzz5.txt | 56 ++ src/relooper/test_fuzz6.cpp | 322 +++++++++ src/relooper/test_fuzz6.txt | 116 ++++ src/relooper/test_inf.cpp | 813 +++++++++++++++++++++++ src/relooper/test_inf.txt | 392 +++++++++++ src/relooper/testit.sh | 60 ++ src/relooper/updateit.sh | 16 + 42 files changed, 4473 insertions(+) create mode 100644 src/relooper/README.markdown create mode 100644 src/relooper/Relooper.cpp create mode 100644 src/relooper/Relooper.h create mode 100755 src/relooper/doit.sh create mode 100644 src/relooper/emscripten/Makefile create mode 100644 src/relooper/emscripten/glue.js create mode 100644 src/relooper/emscripten/test.js create mode 100644 src/relooper/fuzzer.py create mode 100644 src/relooper/ministring.h create mode 100644 src/relooper/paper.pdf create mode 100644 src/relooper/test.cpp create mode 100644 src/relooper/test.txt create mode 100644 src/relooper/test2.c create mode 100644 src/relooper/test2.txt create mode 100644 src/relooper/test3.c create mode 100644 src/relooper/test3.txt create mode 100644 src/relooper/test4.cpp create mode 100644 src/relooper/test4.txt create mode 100644 src/relooper/test5.cpp create mode 100644 src/relooper/test5.txt create mode 100644 src/relooper/test6.cpp create mode 100644 src/relooper/test6.txt create mode 100644 src/relooper/test_dead.cpp create mode 100644 src/relooper/test_dead.txt create mode 100644 src/relooper/test_debug.cpp create mode 100644 src/relooper/test_debug.txt create mode 100644 src/relooper/test_fuzz1.cpp create mode 100644 src/relooper/test_fuzz1.txt create mode 100644 src/relooper/test_fuzz2.cpp create mode 100644 src/relooper/test_fuzz2.txt create mode 100644 src/relooper/test_fuzz3.cpp create mode 100644 src/relooper/test_fuzz3.txt create mode 100644 src/relooper/test_fuzz4.cpp create mode 100644 src/relooper/test_fuzz4.txt create mode 100644 src/relooper/test_fuzz5.cpp create mode 100644 src/relooper/test_fuzz5.txt create mode 100644 src/relooper/test_fuzz6.cpp create mode 100644 src/relooper/test_fuzz6.txt create mode 100644 src/relooper/test_inf.cpp create mode 100644 src/relooper/test_inf.txt create mode 100755 src/relooper/testit.sh create mode 100755 src/relooper/updateit.sh diff --git a/src/relooper/README.markdown b/src/relooper/README.markdown new file mode 100644 index 0000000000000..9b0187b38b380 --- /dev/null +++ b/src/relooper/README.markdown @@ -0,0 +1,14 @@ + +Relooper +======== + +This is an optimized C++ implemention of the Relooper algorithm originally +developed as part of Emscripten. This implementation includes optimizations +added since the original academic paper [1] - see paper.pdf - was published +about it, and is written in an LLVM-friendly way with the goal of inclusion +in upstream LLVM. + +License: MIT&LLVM + +[1] Alon Zakai. 2011. Emscripten: an LLVM-to-JavaScript compiler. In Proceedings of the ACM international conference companion on Object oriented programming systems languages and applications companion (SPLASH '11). ACM, New York, NY, USA, 301-312. DOI=10.1145/2048147.2048224 http://doi.acm.org/10.1145/2048147.2048224 + diff --git a/src/relooper/Relooper.cpp b/src/relooper/Relooper.cpp new file mode 100644 index 0000000000000..f16055c0afb98 --- /dev/null +++ b/src/relooper/Relooper.cpp @@ -0,0 +1,1038 @@ + +#include "Relooper.h" + +#include +#include +#include +#include + +#include "ministring.h" + +// TODO: move all set to unorderedset + +#if DEBUG +static void PrintDebug(const char *Format, ...); +#define DebugDump(x, ...) Debugging::Dump(x, __VA_ARGS__) +#else +#define PrintDebug(x, ...) +#define DebugDump(x, ...) +#endif + +struct Indenter { + static int CurrIndent; + + static void Indent() { CurrIndent++; } + static void Unindent() { CurrIndent--; } +}; + +static void PrintIndented(const char *Format, ...); +static void PutIndented(const char *String); + +static char *OutputBufferRoot = NULL; +static char *OutputBuffer = NULL; +static int OutputBufferSize = 0; + +void PrintIndented(const char *Format, ...) { + assert(OutputBuffer); + assert(OutputBuffer + Indenter::CurrIndent*2 - OutputBufferRoot < OutputBufferSize); + for (int i = 0; i < Indenter::CurrIndent*2; i++, OutputBuffer++) *OutputBuffer = ' '; + va_list Args; + va_start(Args, Format); + int left = OutputBufferSize - (OutputBuffer - OutputBufferRoot); + int written = vsnprintf(OutputBuffer, left, Format, Args); + assert(written < left); + OutputBuffer += written; + va_end(Args); +} + +void PutIndented(const char *String) { + assert(OutputBuffer); + assert(OutputBuffer + Indenter::CurrIndent*2 - OutputBufferRoot < OutputBufferSize); + for (int i = 0; i < Indenter::CurrIndent*2; i++, OutputBuffer++) *OutputBuffer = ' '; + int left = OutputBufferSize - (OutputBuffer - OutputBufferRoot); + int needed = strlen(String)+1; + assert(needed < left); + strcpy(OutputBuffer, String); + OutputBuffer += strlen(String); + *OutputBuffer++ = '\n'; + *OutputBuffer = 0; +} + +// Indenter + +#if EMSCRIPTEN +int Indenter::CurrIndent = 1; +#else +int Indenter::CurrIndent = 0; +#endif + +// Branch + +Branch::Branch(const char *ConditionInit, const char *CodeInit) : Ancestor(NULL), Labeled(false) { + Condition = ConditionInit ? strdup(ConditionInit) : NULL; + Code = CodeInit ? strdup(CodeInit) : NULL; +} + +Branch::~Branch() { + if (Condition) free((void*)Condition); + if (Code) free((void*)Code); +} + +void Branch::Render(Block *Target, bool SetLabel) { + if (Code) PrintIndented("%s\n", Code); + if (SetLabel) PrintIndented("label = %d;\n", Target->Id); + if (Ancestor) { + if (Type != Direct) { + if (Labeled) { + PrintIndented("%s L%d;\n", Type == Break ? "break" : "continue", Ancestor->Id); + } else { + PrintIndented("%s;\n", Type == Break ? "break" : "continue"); + } + } + } +} + +// Block + +int Block::IdCounter = 1; // 0 is reserved for clearings + +Block::Block(const char *CodeInit) : Parent(NULL), Id(Block::IdCounter++), DefaultTarget(NULL), IsCheckedMultipleEntry(false) { + Code = strdup(CodeInit); +} + +Block::~Block() { + if (Code) free((void*)Code); + for (BlockBranchMap::iterator iter = ProcessedBranchesIn.begin(); iter != ProcessedBranchesIn.end(); iter++) { + delete iter->second; + } + for (BlockBranchMap::iterator iter = ProcessedBranchesOut.begin(); iter != ProcessedBranchesOut.end(); iter++) { + delete iter->second; + } + // XXX If not reachable, expected to have branches here. But need to clean them up to prevent leaks! +} + +void Block::AddBranchTo(Block *Target, const char *Condition, const char *Code) { + assert(BranchesOut.find(Target) == BranchesOut.end()); // cannot add more than one branch to the same target + BranchesOut[Target] = new Branch(Condition, Code); +} + +void Block::Render(bool InLoop) { + if (IsCheckedMultipleEntry && InLoop) { + PrintIndented("label = 0;\n"); + } + + if (Code) { + // Print code in an indented manner, even over multiple lines + char *Start = const_cast(Code); + while (*Start) { + char *End = strchr(Start, '\n'); + if (End) *End = 0; + PutIndented(Start); + if (End) *End = '\n'; else break; + Start = End+1; + } + } + + if (!ProcessedBranchesOut.size()) return; + + bool SetLabel = true; // in some cases it is clear we can avoid setting label, see later + + if (ProcessedBranchesOut.size() == 1 && ProcessedBranchesOut.begin()->second->Type == Branch::Direct) { + SetLabel = false; + } + + // A setting of the label variable (label = x) is necessary if it can + // cause an impact. The main case is where we set label to x, then elsewhere + // we check if label is equal to that value, i.e., that label is an entry + // in a multiple block. We also need to reset the label when we enter + // that block, so that each setting is a one-time action: consider + // + // while (1) { + // if (check) label = 1; + // if (label == 1) { label = 0 } + // } + // + // (Note that this case is impossible due to fusing, but that is not + // material here.) So setting to 0 is important just to clear the 1 for + // future iterations. + // TODO: When inside a loop, if necessary clear the label variable + // once on the top, and never do settings that are in effect clears + + // Fusing: If the next is a Multiple, we can fuse it with this block. Note + // that we must be the Inner of a Simple, so fusing means joining a Simple + // to a Multiple. What happens there is that all options in the Multiple + // *must* appear in the Simple (the Simple is the only one reaching the + // Multiple), so we can remove the Multiple and add its independent groups + // into the Simple's branches. + MultipleShape *Fused = Shape::IsMultiple(Parent->Next); + if (Fused) { + PrintDebug("Fusing Multiple to Simple\n"); + Parent->Next = Parent->Next->Next; + Fused->RenderLoopPrefix(); + + // When the Multiple has the same number of groups as we have branches, + // they will all be fused, so it is safe to not set the label at all + if (SetLabel && Fused->InnerMap.size() == ProcessedBranchesOut.size()) { + SetLabel = false; + } + } + + // We must do this here, because blocks can be split and even comparing their Ids is not enough. We must check the conditions. + for (BlockBranchMap::iterator iter = ProcessedBranchesOut.begin(); iter != ProcessedBranchesOut.end(); iter++) { + if (!iter->second->Condition) { + assert(!DefaultTarget); // Must be exactly one default + DefaultTarget = iter->first; + } + } + assert(DefaultTarget); // Must be a default + + ministring RemainingConditions; + bool First = true; + for (BlockBranchMap::iterator iter = ProcessedBranchesOut.begin();; iter++) { + Block *Target; + Branch *Details; + if (iter != ProcessedBranchesOut.end()) { + Target = iter->first; + if (Target == DefaultTarget) continue; // done at the end + Details = iter->second; + assert(Details->Condition); // must have a condition if this is not the default target + } else { + Target = DefaultTarget; + Details = ProcessedBranchesOut[DefaultTarget]; + } + bool SetCurrLabel = SetLabel && Target->IsCheckedMultipleEntry; + bool HasFusedContent = Fused && Fused->InnerMap.find(Target) != Fused->InnerMap.end(); + bool HasContent = SetCurrLabel || Details->Type != Branch::Direct || HasFusedContent || Details->Code; + if (iter != ProcessedBranchesOut.end()) { + // If there is nothing to show in this branch, omit the condition + if (HasContent) { + PrintIndented("%sif (%s) {\n", First ? "" : "} else ", Details->Condition); + First = false; + } else { + if (RemainingConditions.size() > 0) RemainingConditions += " && "; + RemainingConditions += "!("; + RemainingConditions += Details->Condition; + RemainingConditions += ")"; + } + } else { + if (HasContent) { + if (RemainingConditions.size() > 0) { + if (First) { + PrintIndented("if (%s) {\n", RemainingConditions.c_str()); + First = false; + } else { + PrintIndented("} else if (%s) {\n", RemainingConditions.c_str()); + } + } else if (!First) { + PrintIndented("} else {\n"); + } + } + } + if (!First) Indenter::Indent(); + Details->Render(Target, SetCurrLabel); + if (HasFusedContent) { + Fused->InnerMap.find(Target)->second->Render(InLoop); + } + if (!First) Indenter::Unindent(); + if (iter == ProcessedBranchesOut.end()) break; + } + if (!First) PrintIndented("}\n"); + + if (Fused) { + Fused->RenderLoopPostfix(); + } +} + +// Shape + +int Shape::IdCounter = 0; + +// MultipleShape + +void MultipleShape::RenderLoopPrefix() { + if (NeedLoop) { + if (Labeled) { + PrintIndented("L%d: do {\n", Id); + } else { + PrintIndented("do {\n"); + } + Indenter::Indent(); + } +} + +void MultipleShape::RenderLoopPostfix() { + if (NeedLoop) { + Indenter::Unindent(); + PrintIndented("} while(0);\n"); + } +} + +void MultipleShape::Render(bool InLoop) { + RenderLoopPrefix(); + bool First = true; + for (BlockShapeMap::iterator iter = InnerMap.begin(); iter != InnerMap.end(); iter++) { + PrintIndented("%sif (label == %d) {\n", First ? "" : "else ", iter->first->Id); + First = false; + Indenter::Indent(); + iter->second->Render(InLoop); + Indenter::Unindent(); + PrintIndented("}\n"); + } + RenderLoopPostfix(); + if (Next) Next->Render(InLoop); +}; + +// LoopShape + +void LoopShape::Render(bool InLoop) { + if (Labeled) { + PrintIndented("L%d: while(1) {\n", Id); + } else { + PrintIndented("while(1) {\n"); + } + Indenter::Indent(); + Inner->Render(true); + Indenter::Unindent(); + PrintIndented("}\n"); + if (Next) Next->Render(InLoop); +}; + +/* +// EmulatedShape + +void EmulatedShape::Render(bool InLoop) { + PrintIndented("while(1) {\n"); + Indenter::Indent(); + PrintIndented("switch(label) {\n"); + Indenter::Indent(); + for (int i = 0; i < Blocks.size(); i++) { + Block *Curr = Blocks[i]; + PrintIndented("case %d: {\n", Curr->Id); + Indenter::Indent(); + Curr->Render(InLoop); + PrintIndented("break;\n"); + Indenter::Unindent(); + PrintIndented("}\n"); + } + Indenter::Unindent(); + PrintIndented("}\n"); + Indenter::Unindent(); + PrintIndented("}\n"); + if (Next) Next->Render(InLoop); +}; +*/ + +// Relooper + +Relooper::Relooper() : Root(NULL) { +} + +Relooper::~Relooper() { + for (int i = 0; i < Blocks.size(); i++) delete Blocks[i]; + for (int i = 0; i < Shapes.size(); i++) delete Shapes[i]; +} + +void Relooper::AddBlock(Block *New) { + Blocks.push_back(New); +} + +struct RelooperRecursor { + Relooper *Parent; + RelooperRecursor(Relooper *ParentInit) : Parent(ParentInit) {} +}; + +void Relooper::Calculate(Block *Entry) { + // Scan and optimize the input + struct PreOptimizer : public RelooperRecursor { + PreOptimizer(Relooper *Parent) : RelooperRecursor(Parent) {} + BlockSet Live; + + void FindLive(Block *Curr) { + if (Live.find(Curr) != Live.end()) return; + Live.insert(Curr); + for (BlockBranchMap::iterator iter = Curr->BranchesOut.begin(); iter != Curr->BranchesOut.end(); iter++) { + FindLive(iter->first); + } + } + + // If a block has multiple entries but no exits, and it is small enough, it is useful to split it. + // A common example is a C++ function where everything ends up at a final exit block and does some + // RAII cleanup. Without splitting, we will be forced to introduce labelled loops to allow + // reaching the final block + void SplitDeadEnds() { + int TotalCodeSize = 0; + for (BlockSet::iterator iter = Live.begin(); iter != Live.end(); iter++) { + Block *Curr = *iter; + TotalCodeSize += strlen(Curr->Code); + } + + for (BlockSet::iterator iter = Live.begin(); iter != Live.end(); iter++) { + Block *Original = *iter; + if (Original->BranchesIn.size() <= 1 || Original->BranchesOut.size() > 0) continue; + if (strlen(Original->Code)*(Original->BranchesIn.size()-1) > TotalCodeSize/5) continue; // if splitting increases raw code size by a significant amount, abort + // Split the node (for simplicity, we replace all the blocks, even though we could have reused the original) + for (BlockBranchMap::iterator iter = Original->BranchesIn.begin(); iter != Original->BranchesIn.end(); iter++) { + Block *Prior = iter->first; + Block *Split = new Block(Original->Code); + Split->BranchesIn[Prior] = new Branch(NULL); + Prior->BranchesOut[Split] = new Branch(Prior->BranchesOut[Original]->Condition, Prior->BranchesOut[Original]->Code); + Prior->BranchesOut.erase(Original); + Parent->AddBlock(Split); + Live.insert(Split); + } + } + } + }; + PreOptimizer Pre(this); + Pre.FindLive(Entry); + + // Add incoming branches from live blocks, ignoring dead code + for (int i = 0; i < Blocks.size(); i++) { + Block *Curr = Blocks[i]; + if (Pre.Live.find(Curr) == Pre.Live.end()) continue; + for (BlockBranchMap::iterator iter = Curr->BranchesOut.begin(); iter != Curr->BranchesOut.end(); iter++) { + iter->first->BranchesIn[Curr] = new Branch(NULL); + } + } + + Pre.SplitDeadEnds(); + + // Recursively process the graph + + struct Analyzer : public RelooperRecursor { + Analyzer(Relooper *Parent) : RelooperRecursor(Parent) {} + + // Add a shape to the list of shapes in this Relooper calculation + void Notice(Shape *New) { + Parent->Shapes.push_back(New); + } + + // Create a list of entries from a block. If LimitTo is provided, only results in that set + // will appear + void GetBlocksOut(Block *Source, BlockSet& Entries, BlockSet *LimitTo=NULL) { + for (BlockBranchMap::iterator iter = Source->BranchesOut.begin(); iter != Source->BranchesOut.end(); iter++) { + if (!LimitTo || LimitTo->find(iter->first) != LimitTo->end()) { + Entries.insert(iter->first); + } + } + } + + // Converts/processes all branchings to a specific target + void Solipsize(Block *Target, Branch::FlowType Type, Shape *Ancestor, BlockSet &From) { + PrintDebug("Solipsizing branches into %d\n", Target->Id); + DebugDump(From, " relevant to solipsize: "); + for (BlockBranchMap::iterator iter = Target->BranchesIn.begin(); iter != Target->BranchesIn.end();) { + Block *Prior = iter->first; + if (From.find(Prior) == From.end()) { + iter++; + continue; + } + Branch *TargetIn = iter->second; + Branch *PriorOut = Prior->BranchesOut[Target]; + PriorOut->Ancestor = Ancestor; // Do we need this info + PriorOut->Type = Type; // on TargetIn too? + if (MultipleShape *Multiple = Shape::IsMultiple(Ancestor)) { + Multiple->NeedLoop++; // We are breaking out of this Multiple, so need a loop + } + iter++; // carefully increment iter before erasing + Target->BranchesIn.erase(Prior); + Target->ProcessedBranchesIn[Prior] = TargetIn; + Prior->BranchesOut.erase(Target); + Prior->ProcessedBranchesOut[Target] = PriorOut; + PrintDebug(" eliminated branch from %d\n", Prior->Id); + } + } + + Shape *MakeSimple(BlockSet &Blocks, Block *Inner, BlockSet &NextEntries) { + PrintDebug("creating simple block with block #%d\n", Inner->Id); + SimpleShape *Simple = new SimpleShape; + Notice(Simple); + Simple->Inner = Inner; + Inner->Parent = Simple; + if (Blocks.size() > 1) { + Blocks.erase(Inner); + GetBlocksOut(Inner, NextEntries, &Blocks); + BlockSet JustInner; + JustInner.insert(Inner); + for (BlockSet::iterator iter = NextEntries.begin(); iter != NextEntries.end(); iter++) { + Solipsize(*iter, Branch::Direct, Simple, JustInner); + } + } + return Simple; + } + + Shape *MakeLoop(BlockSet &Blocks, BlockSet& Entries, BlockSet &NextEntries) { + // Find the inner blocks in this loop. Proceed backwards from the entries until + // you reach a seen block, collecting as you go. + BlockSet InnerBlocks; + BlockSet Queue = Entries; + while (Queue.size() > 0) { + Block *Curr = *(Queue.begin()); + Queue.erase(Queue.begin()); + if (InnerBlocks.find(Curr) == InnerBlocks.end()) { + // This element is new, mark it as inner and remove from outer + InnerBlocks.insert(Curr); + Blocks.erase(Curr); + // Add the elements prior to it + for (BlockBranchMap::iterator iter = Curr->BranchesIn.begin(); iter != Curr->BranchesIn.end(); iter++) { + Queue.insert(iter->first); + } + } + } + assert(InnerBlocks.size() > 0); + + for (BlockSet::iterator iter = InnerBlocks.begin(); iter != InnerBlocks.end(); iter++) { + Block *Curr = *iter; + for (BlockBranchMap::iterator iter = Curr->BranchesOut.begin(); iter != Curr->BranchesOut.end(); iter++) { + Block *Possible = iter->first; + if (InnerBlocks.find(Possible) == InnerBlocks.end() && + NextEntries.find(Possible) == NextEntries.find(Possible)) { + NextEntries.insert(Possible); + } + } + } + + PrintDebug("creating loop block:\n"); + DebugDump(InnerBlocks, " inner blocks:"); + DebugDump(Entries, " inner entries:"); + DebugDump(Blocks, " outer blocks:"); + DebugDump(NextEntries, " outer entries:"); + + // TODO: Optionally hoist additional blocks into the loop + + LoopShape *Loop = new LoopShape(); + Notice(Loop); + + // Solipsize the loop, replacing with break/continue and marking branches as Processed (will not affect later calculations) + // A. Branches to the loop entries become a continue to this shape + for (BlockSet::iterator iter = Entries.begin(); iter != Entries.end(); iter++) { + Solipsize(*iter, Branch::Continue, Loop, InnerBlocks); + } + // B. Branches to outside the loop (a next entry) become breaks on this shape + for (BlockSet::iterator iter = NextEntries.begin(); iter != NextEntries.end(); iter++) { + Solipsize(*iter, Branch::Break, Loop, InnerBlocks); + } + // Finish up + Shape *Inner = Process(InnerBlocks, Entries, NULL); + Loop->Inner = Inner; + return Loop; + } + + // For each entry, find the independent group reachable by it. The independent group is + // the entry itself, plus all the blocks it can reach that cannot be directly reached by another entry. Note that we + // ignore directly reaching the entry itself by another entry. + void FindIndependentGroups(BlockSet &Blocks, BlockSet &Entries, BlockBlockSetMap& IndependentGroups) { + typedef std::map BlockBlockMap; + typedef std::list BlockList; + + struct HelperClass { + BlockBlockSetMap& IndependentGroups; + BlockBlockMap Ownership; // For each block, which entry it belongs to. We have reached it from there. + + HelperClass(BlockBlockSetMap& IndependentGroupsInit) : IndependentGroups(IndependentGroupsInit) {} + void InvalidateWithChildren(Block *New) { // TODO: rename New + BlockList ToInvalidate; // Being in the list means you need to be invalidated + ToInvalidate.push_back(New); + while (ToInvalidate.size() > 0) { + Block *Invalidatee = ToInvalidate.front(); + ToInvalidate.pop_front(); + Block *Owner = Ownership[Invalidatee]; + if (IndependentGroups.find(Owner) != IndependentGroups.end()) { // Owner may have been invalidated, do not add to IndependentGroups! + IndependentGroups[Owner].erase(Invalidatee); + } + if (Ownership[Invalidatee]) { // may have been seen before and invalidated already + Ownership[Invalidatee] = NULL; + for (BlockBranchMap::iterator iter = Invalidatee->BranchesOut.begin(); iter != Invalidatee->BranchesOut.end(); iter++) { + Block *Target = iter->first; + BlockBlockMap::iterator Known = Ownership.find(Target); + if (Known != Ownership.end()) { + Block *TargetOwner = Known->second; + if (TargetOwner) { + ToInvalidate.push_back(Target); + } + } + } + } + } + } + }; + HelperClass Helper(IndependentGroups); + + // We flow out from each of the entries, simultaneously. + // When we reach a new block, we add it as belonging to the one we got to it from. + // If we reach a new block that is already marked as belonging to someone, it is reachable by + // two entries and is not valid for any of them. Remove it and all it can reach that have been + // visited. + + BlockList Queue; // Being in the queue means we just added this item, and we need to add its children + for (BlockSet::iterator iter = Entries.begin(); iter != Entries.end(); iter++) { + Block *Entry = *iter; + Helper.Ownership[Entry] = Entry; + IndependentGroups[Entry].insert(Entry); + Queue.push_back(Entry); + } + while (Queue.size() > 0) { + Block *Curr = Queue.front(); + Queue.pop_front(); + Block *Owner = Helper.Ownership[Curr]; // Curr must be in the ownership map if we are in the queue + if (!Owner) continue; // we have been invalidated meanwhile after being reached from two entries + // Add all children + for (BlockBranchMap::iterator iter = Curr->BranchesOut.begin(); iter != Curr->BranchesOut.end(); iter++) { + Block *New = iter->first; + BlockBlockMap::iterator Known = Helper.Ownership.find(New); + if (Known == Helper.Ownership.end()) { + // New node. Add it, and put it in the queue + Helper.Ownership[New] = Owner; + IndependentGroups[Owner].insert(New); + Queue.push_back(New); + continue; + } + Block *NewOwner = Known->second; + if (!NewOwner) continue; // We reached an invalidated node + if (NewOwner != Owner) { + // Invalidate this and all reachable that we have seen - we reached this from two locations + Helper.InvalidateWithChildren(New); + } + // otherwise, we have the same owner, so do nothing + } + } + + // Having processed all the interesting blocks, we remain with just one potential issue: + // If a->b, and a was invalidated, but then b was later reached by someone else, we must + // invalidate b. To check for this, we go over all elements in the independent groups, + // if an element has a parent which does *not* have the same owner, we must remove it + // and all its children. + + for (BlockSet::iterator iter = Entries.begin(); iter != Entries.end(); iter++) { + BlockSet &CurrGroup = IndependentGroups[*iter]; + BlockList ToInvalidate; + for (BlockSet::iterator iter = CurrGroup.begin(); iter != CurrGroup.end(); iter++) { + Block *Child = *iter; + for (BlockBranchMap::iterator iter = Child->BranchesIn.begin(); iter != Child->BranchesIn.end(); iter++) { + Block *Parent = iter->first; + if (Helper.Ownership[Parent] != Helper.Ownership[Child]) { + ToInvalidate.push_back(Child); + } + } + } + while (ToInvalidate.size() > 0) { + Block *Invalidatee = ToInvalidate.front(); + ToInvalidate.pop_front(); + Helper.InvalidateWithChildren(Invalidatee); + } + } + + // Remove empty groups + for (BlockSet::iterator iter = Entries.begin(); iter != Entries.end(); iter++) { + if (IndependentGroups[*iter].size() == 0) { + IndependentGroups.erase(*iter); + } + } + +#if DEBUG + PrintDebug("Investigated independent groups:\n"); + for (BlockBlockSetMap::iterator iter = IndependentGroups.begin(); iter != IndependentGroups.end(); iter++) { + DebugDump(iter->second, " group: "); + } +#endif + } + + Shape *MakeMultiple(BlockSet &Blocks, BlockSet& Entries, BlockBlockSetMap& IndependentGroups, Shape *Prev, BlockSet &NextEntries) { + PrintDebug("creating multiple block with %d inner groups\n", IndependentGroups.size()); + bool Fused = !!(Shape::IsSimple(Prev)); + MultipleShape *Multiple = new MultipleShape(); + Notice(Multiple); + BlockSet CurrEntries; + for (BlockBlockSetMap::iterator iter = IndependentGroups.begin(); iter != IndependentGroups.end(); iter++) { + Block *CurrEntry = iter->first; + BlockSet &CurrBlocks = iter->second; + PrintDebug(" multiple group with entry %d:\n", CurrEntry->Id); + DebugDump(CurrBlocks, " "); + // Create inner block + CurrEntries.clear(); + CurrEntries.insert(CurrEntry); + for (BlockSet::iterator iter = CurrBlocks.begin(); iter != CurrBlocks.end(); iter++) { + Block *CurrInner = *iter; + // Remove the block from the remaining blocks + Blocks.erase(CurrInner); + // Find new next entries and fix branches to them + for (BlockBranchMap::iterator iter = CurrInner->BranchesOut.begin(); iter != CurrInner->BranchesOut.end();) { + Block *CurrTarget = iter->first; + BlockBranchMap::iterator Next = iter; + Next++; + if (CurrBlocks.find(CurrTarget) == CurrBlocks.end()) { + NextEntries.insert(CurrTarget); + Solipsize(CurrTarget, Branch::Break, Multiple, CurrBlocks); + } + iter = Next; // increment carefully because Solipsize can remove us + } + } + Multiple->InnerMap[CurrEntry] = Process(CurrBlocks, CurrEntries, NULL); + // If we are not fused, then our entries will actually be checked + if (!Fused) { + CurrEntry->IsCheckedMultipleEntry = true; + } + } + DebugDump(Blocks, " remaining blocks after multiple:"); + // Add entries not handled as next entries, they are deferred + for (BlockSet::iterator iter = Entries.begin(); iter != Entries.end(); iter++) { + Block *Entry = *iter; + if (IndependentGroups.find(Entry) == IndependentGroups.end()) { + NextEntries.insert(Entry); + } + } + return Multiple; + } + + // Main function. + // Process a set of blocks with specified entries, returns a shape + // The Make* functions receive a NextEntries. If they fill it with data, those are the entries for the + // ->Next block on them, and the blocks are what remains in Blocks (which Make* modify). In this way + // we avoid recursing on Next (imagine a long chain of Simples, if we recursed we could blow the stack). + Shape *Process(BlockSet &Blocks, BlockSet& InitialEntries, Shape *Prev) { + PrintDebug("Process() called\n"); + BlockSet *Entries = &InitialEntries; + BlockSet TempEntries[2]; + int CurrTempIndex = 0; + BlockSet *NextEntries; + Shape *Ret = NULL; + #define Make(call) \ + Shape *Temp = call; \ + if (Prev) Prev->Next = Temp; \ + if (!Ret) Ret = Temp; \ + if (!NextEntries->size()) { PrintDebug("Process() returning\n"); return Ret; } \ + Prev = Temp; \ + Entries = NextEntries; \ + continue; + while (1) { + PrintDebug("Process() running\n"); + DebugDump(Blocks, " blocks : "); + DebugDump(*Entries, " entries: "); + + CurrTempIndex = 1-CurrTempIndex; + NextEntries = &TempEntries[CurrTempIndex]; + NextEntries->clear(); + + if (Entries->size() == 0) return Ret; + if (Entries->size() == 1) { + Block *Curr = *(Entries->begin()); + if (Curr->BranchesIn.size() == 0) { + // One entry, no looping ==> Simple + Make(MakeSimple(Blocks, Curr, *NextEntries)); + } + // One entry, looping ==> Loop + Make(MakeLoop(Blocks, *Entries, *NextEntries)); + } + // More than one entry, try to eliminate through a Multiple groups of + // independent blocks from an entry/ies. It is important to remove through + // multiples as opposed to looping since the former is more performant. + BlockBlockSetMap IndependentGroups; + FindIndependentGroups(Blocks, *Entries, IndependentGroups); + + PrintDebug("Independent groups: %d\n", IndependentGroups.size()); + + if (IndependentGroups.size() > 0) { + // We can handle a group in a multiple if its entry cannot be reached by another group. + // Note that it might be reachable by itself - a loop. But that is fine, we will create + // a loop inside the multiple block (which is the performant order to do it). + for (BlockBlockSetMap::iterator iter = IndependentGroups.begin(); iter != IndependentGroups.end();) { + Block *Entry = iter->first; + BlockSet &Group = iter->second; + BlockBlockSetMap::iterator curr = iter++; // iterate carefully, we may delete + for (BlockBranchMap::iterator iterBranch = Entry->BranchesIn.begin(); iterBranch != Entry->BranchesIn.end(); iterBranch++) { + Block *Origin = iterBranch->first; + if (Group.find(Origin) == Group.end()) { + // Reached from outside the group, so we cannot handle this + PrintDebug("Cannot handle group with entry %d because of incoming branch from %d\n", Entry->Id, Origin->Id); + IndependentGroups.erase(curr); + break; + } + } + } + + PrintDebug("Handleable independent groups: %d\n", IndependentGroups.size()); + + if (IndependentGroups.size() > 0) { + // Some groups removable ==> Multiple + Make(MakeMultiple(Blocks, *Entries, IndependentGroups, Prev, *NextEntries)); + } + } + // No independent groups, must be loopable ==> Loop + Make(MakeLoop(Blocks, *Entries, *NextEntries)); + } + } + }; + + // Main + + BlockSet AllBlocks; + for (int i = 0; i < Blocks.size(); i++) { + AllBlocks.insert(Blocks[i]); +#if DEBUG + PrintDebug("Adding block %d (%s)\n", Blocks[i]->Id, Blocks[i]->Code); + for (BlockBranchMap::iterator iter = Blocks[i]->BranchesOut.begin(); iter != Blocks[i]->BranchesOut.end(); iter++) { + PrintDebug(" with branch out to %d\n", iter->first->Id); + } +#endif + } + + BlockSet Entries; + Entries.insert(Entry); + Root = Analyzer(this).Process(AllBlocks, Entries, NULL); + + // Post optimizations + + struct PostOptimizer { + Relooper *Parent; + void *Closure; + + PostOptimizer(Relooper *ParentInit) : Parent(ParentInit), Closure(NULL) {} + + #define RECURSE_MULTIPLE_MANUAL(func, manual) \ + for (BlockShapeMap::iterator iter = manual->InnerMap.begin(); iter != manual->InnerMap.end(); iter++) { \ + func(iter->second); \ + } + #define RECURSE_MULTIPLE(func) RECURSE_MULTIPLE_MANUAL(func, Multiple); + #define RECURSE_LOOP(func) \ + func(Loop->Inner); + + #define SHAPE_SWITCH(var, simple, multiple, loop) \ + if (SimpleShape *Simple = Shape::IsSimple(var)) { \ + simple; \ + } else if (MultipleShape *Multiple = Shape::IsMultiple(var)) { \ + multiple; \ + } else if (LoopShape *Loop = Shape::IsLoop(var)) { \ + loop; \ + } + + #define SHAPE_SWITCH_AUTO(var, simple, multiple, loop, func) \ + if (SimpleShape *Simple = Shape::IsSimple(var)) { \ + simple; \ + func(Simple->Next); \ + } else if (MultipleShape *Multiple = Shape::IsMultiple(var)) { \ + multiple; \ + RECURSE_MULTIPLE(func) \ + func(Multiple->Next); \ + } else if (LoopShape *Loop = Shape::IsLoop(var)) { \ + loop; \ + RECURSE_LOOP(func); \ + func(Loop->Next); \ + } + + // 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) { + SHAPE_SWITCH(Root, { + // If there is a next block, we already know at Simple creation time to make direct branches, + // and we can do nothing more. If there is no next however, then Natural is where we will + // go to by doing nothing, so we can potentially optimize some branches to direct. + if (Simple->Next) { + RemoveUnneededFlows(Simple->Next, Natural); + } else { + 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) { + Details->Type = Branch::Direct; + if (MultipleShape *Multiple = Shape::IsMultiple(Details->Ancestor)) { + Multiple->NeedLoop--; + } + } + } + } + }, { + for (BlockShapeMap::iterator iter = Multiple->InnerMap.begin(); iter != Multiple->InnerMap.end(); iter++) { + RemoveUnneededFlows(iter->second, Multiple->Next); + } + RemoveUnneededFlows(Multiple->Next, Natural); + }, { + RemoveUnneededFlows(Loop->Inner, Loop->Inner); + RemoveUnneededFlows(Loop->Next, Natural); + }); + } + + // After we know which loops exist, we can calculate which need to be labeled + void FindLabeledLoops(Shape *Root) { + bool First = Closure == NULL; + if (First) { + Closure = (void*)(new std::stack); + } + std::stack &LoopStack = *((std::stack*)Closure); + + SHAPE_SWITCH(Root, { + MultipleShape *Fused = Shape::IsMultiple(Root->Next); + // If we are fusing a Multiple with a loop into this Simple, then visit it now + if (Fused && Fused->NeedLoop) { + LoopStack.push(Fused); + RECURSE_MULTIPLE_MANUAL(FindLabeledLoops, Fused); + } + 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) { + assert(LoopStack.size() > 0); + if (Details->Ancestor != LoopStack.top()) { + LabeledShape *Labeled = Shape::IsLabeled(Details->Ancestor); + Labeled->Labeled = true; + Details->Labeled = true; + } else { + Details->Labeled = false; + } + } + } + if (Fused && Fused->NeedLoop) { + LoopStack.pop(); + if (Fused->Next) FindLabeledLoops(Fused->Next); + } else { + if (Root->Next) FindLabeledLoops(Root->Next); + } + }, { + if (Multiple->NeedLoop) { + LoopStack.push(Multiple); + } + RECURSE_MULTIPLE(FindLabeledLoops); + if (Multiple->NeedLoop) { + LoopStack.pop(); + } + if (Root->Next) FindLabeledLoops(Root->Next); + }, { + LoopStack.push(Loop); + RECURSE_LOOP(FindLabeledLoops); + LoopStack.pop(); + if (Root->Next) FindLabeledLoops(Root->Next); + }); + + if (First) { + delete (std::stack*)Closure; + } + } + + void Process(Shape *Root) { + RemoveUnneededFlows(Root); + FindLabeledLoops(Root); + } + }; + + PrintDebug("=== Optimizing shapes ===\n"); + + PostOptimizer(this).Process(Root); +} + +void Relooper::Render() { + OutputBuffer = OutputBufferRoot; + Root->Render(false); +} + +void Relooper::SetOutputBuffer(char *Buffer, int Size) { + OutputBufferRoot = OutputBuffer = Buffer; + OutputBufferSize = Size; +} + +void Relooper::MakeOutputBuffer(int Size) { + OutputBufferRoot = OutputBuffer = (char*)malloc(Size); + OutputBufferSize = Size; +} + +#if DEBUG +// Debugging + +void DebugDump(BlockSet &Blocks, const char *prefix) { + if (prefix) printf("%s ", prefix); + for (BlockSet::iterator iter = Blocks.begin(); iter != Blocks.end(); iter++) { + printf("%d ", (*iter)->Id); + } + printf("\n"); +} + +static void PrintDebug(const char *Format, ...) { + printf("// "); + va_list Args; + va_start(Args, Format); + vprintf(Format, Args); + va_end(Args); +} +#endif + +// C API - useful for binding to other languages + +typedef std::map VoidIntMap; +VoidIntMap __blockDebugMap__; // maps block pointers in currently running code to block ids, for generated debug output + +extern "C" { + +void rl_set_output_buffer(char *buffer, int size) { +#if DEBUG + printf("#include \"Relooper.h\"\n"); + printf("int main() {\n"); + printf(" char buffer[100000];\n"); + printf(" rl_set_output_buffer(buffer);\n"); +#endif + Relooper::SetOutputBuffer(buffer, size); +} + +void rl_make_output_buffer(int size) { + Relooper::SetOutputBuffer((char*)malloc(size), size); +} + +void *rl_new_block(const char *text) { + Block *ret = new Block(text); +#if DEBUG + printf(" void *b%d = rl_new_block(\"// code %d\");\n", ret->Id, ret->Id); + __blockDebugMap__[ret] = ret->Id; + printf(" block_map[%d] = b%d;\n", ret->Id, ret->Id); +#endif + return ret; +} + +void rl_delete_block(void *block) { +#if DEBUG + printf(" rl_delete_block(block_map[%d]);\n", ((Block*)block)->Id); +#endif + delete (Block*)block; +} + +void rl_block_add_branch_to(void *from, void *to, const char *condition, const char *code) { +#if DEBUG + printf(" rl_block_add_branch_to(block_map[%d], block_map[%d], %s%s%s, %s%s%s);\n", ((Block*)from)->Id, ((Block*)to)->Id, condition ? "\"" : "", condition ? condition : "NULL", condition ? "\"" : "", code ? "\"" : "", code ? code : "NULL", code ? "\"" : ""); +#endif + ((Block*)from)->AddBranchTo((Block*)to, condition, code); +} + +void *rl_new_relooper() { +#if DEBUG + printf(" void *block_map[10000];\n"); + printf(" void *rl = rl_new_relooper();\n"); +#endif + return new Relooper; +} + +void rl_delete_relooper(void *relooper) { + delete (Relooper*)relooper; +} + +void rl_relooper_add_block(void *relooper, void *block) { +#if DEBUG + printf(" rl_relooper_add_block(rl, block_map[%d]);\n", ((Block*)block)->Id); +#endif + ((Relooper*)relooper)->AddBlock((Block*)block); +} + +void rl_relooper_calculate(void *relooper, void *entry) { +#if DEBUG + printf(" rl_relooper_calculate(rl, block_map[%d]);\n", ((Block*)entry)->Id); + printf(" rl_relooper_render(rl);\n"); + printf(" rl_delete_relooper(rl);\n"); + printf(" puts(buffer);\n"); + printf(" return 0;\n"); + printf("}\n"); +#endif + ((Relooper*)relooper)->Calculate((Block*)entry); +} + +void rl_relooper_render(void *relooper) { + ((Relooper*)relooper)->Render(); +} + +} + diff --git a/src/relooper/Relooper.h b/src/relooper/Relooper.h new file mode 100644 index 0000000000000..08ac8e4015336 --- /dev/null +++ b/src/relooper/Relooper.h @@ -0,0 +1,246 @@ +/* +This is an optimized C++ implemention of the Relooper algorithm originally +developed as part of Emscripten. This implementation includes optimizations +added since the original academic paper [1] was published about it, and is +written in an LLVM-friendly way with the goal of inclusion in upstream +LLVM. + +[1] Alon Zakai. 2011. Emscripten: an LLVM-to-JavaScript compiler. In Proceedings of the ACM international conference companion on Object oriented programming systems languages and applications companion (SPLASH '11). ACM, New York, NY, USA, 301-312. DOI=10.1145/2048147.2048224 http://doi.acm.org/10.1145/2048147.2048224 +*/ + +#include +#include +#include + +#ifdef __cplusplus + +#include +#include +#include + +struct Block; +struct Shape; + +// Info about a branching from one block to another +struct Branch { + enum FlowType { + Direct = 0, // We will directly reach the right location through other means, no need for continue or break + Break = 1, + Continue = 2 + }; + Shape *Ancestor; // If not NULL, this shape is the relevant one for purposes of getting to the target block. We break or continue on it + Branch::FlowType Type; // If Ancestor is not NULL, this says whether to break or continue + bool Labeled; // If a break or continue, whether we need to use a label + const char *Condition; // The condition for which we branch. For example, "my_var == 1". Conditions are checked one by one. One of the conditions should have NULL as the condition, in which case it is the default + const char *Code; // If provided, code that is run right before the branch is taken. This is useful for phis + + Branch(const char *ConditionInit, const char *CodeInit=NULL); + ~Branch(); + + // Prints out the branch + void Render(Block *Target, bool SetLabel); +}; + +typedef std::map BlockBranchMap; + +// Represents a basic block of code - some instructions that end with a +// control flow modifier (a branch, return or throw). +struct Block { + // Branches become processed after we finish the shape relevant to them. For example, + // when we recreate a loop, branches to the loop start become continues and are now + // processed. When we calculate what shape to generate from a set of blocks, we ignore + // processed branches. + // Blocks own the Branch objects they use, and destroy them when done. + BlockBranchMap BranchesOut; + BlockBranchMap BranchesIn; // TODO: make this just a list of Incoming, without branch info - should be just on BranchesOut + BlockBranchMap ProcessedBranchesOut; + BlockBranchMap ProcessedBranchesIn; + Shape *Parent; // The shape we are directly inside + int Id; // A unique identifier + const char *Code; // The string representation of the code in this block. Owning pointer (we copy the input) + Block *DefaultTarget; // The block we branch to without checking the condition, if none of the other conditions held. + // Since each block *must* branch somewhere, this must be set + bool IsCheckedMultipleEntry; // If true, we are a multiple entry, so reaching us requires setting the label variable + + Block(const char *CodeInit); + ~Block(); + + void AddBranchTo(Block *Target, const char *Condition, const char *Code=NULL); + + // Prints out the instructions code and branchings + void Render(bool InLoop); + + // INTERNAL + static int IdCounter; +}; + +// Represents a structured control flow shape, one of +// +// Simple: No control flow at all, just instructions. If several +// blocks, then +// +// Multiple: A shape with more than one entry. If the next block to +// be entered is among them, we run it and continue to +// the next shape, otherwise we continue immediately to the +// next shape. +// +// Loop: An infinite loop. +// +// Emulated: Control flow is managed by a switch in a loop. This +// is necessary in some cases, for example when control +// flow is not known until runtime (indirect branches, +// setjmp returns, etc.) +// + +class SimpleShape; +class LabeledShape; +class MultipleShape; +class LoopShape; + +struct Shape { + int Id; // A unique identifier. Used to identify loops, labels are Lx where x is the Id. + Shape *Next; // The shape that will appear in the code right after this one + + enum ShapeType { + Simple, + Multiple, + Loop + }; + ShapeType Type; + + Shape(ShapeType TypeInit) : Id(Shape::IdCounter++), Next(NULL), Type(TypeInit) {} + virtual ~Shape() {} + + virtual void Render(bool InLoop) = 0; + + static SimpleShape *IsSimple(Shape *It) { return It && It->Type == Simple ? (SimpleShape*)It : NULL; } + static MultipleShape *IsMultiple(Shape *It) { return It && It->Type == Multiple ? (MultipleShape*)It : NULL; } + static LoopShape *IsLoop(Shape *It) { return It && It->Type == Loop ? (LoopShape*)It : NULL; } + static LabeledShape *IsLabeled(Shape *It) { return IsMultiple(It) || IsLoop(It) ? (LabeledShape*)It : NULL; } + + // INTERNAL + static int IdCounter; +}; + +struct SimpleShape : public Shape { + Block *Inner; + + SimpleShape() : Shape(Simple), Inner(NULL) {} + void Render(bool InLoop) { + Inner->Render(InLoop); + if (Next) Next->Render(InLoop); + } +}; + +typedef std::map BlockShapeMap; + +// A shape that may be implemented with a labeled loop. +struct LabeledShape : public Shape { + bool Labeled; // If we have a loop, whether it needs to be labeled + + LabeledShape(ShapeType TypeInit) : Shape(TypeInit), Labeled(false) {} +}; + +struct MultipleShape : public LabeledShape { + BlockShapeMap InnerMap; // entry block -> shape + int NeedLoop; // If we have branches, we need a loop. This is a counter of loop requirements, + // if we optimize it to 0, the loop is unneeded + + MultipleShape() : LabeledShape(Multiple), NeedLoop(0) {} + + void RenderLoopPrefix(); + void RenderLoopPostfix(); + + void Render(bool InLoop); +}; + +struct LoopShape : public LabeledShape { + Shape *Inner; + + LoopShape() : LabeledShape(Loop), Inner(NULL) {} + void Render(bool InLoop); +}; + +/* +struct EmulatedShape : public Shape { + std::deque Blocks; + void Render(bool InLoop); +}; +*/ + +// Implements the relooper algorithm for a function's blocks. +// +// Usage: +// 1. Instantiate this struct. +// 2. Call AddBlock with the blocks you have. Each should already +// have its branchings in specified (the branchings out will +// be calculated by the relooper). +// 3. Call Render(). +// +// Implementation details: The Relooper instance has +// ownership of the blocks and shapes, and frees them when done. +struct Relooper { + std::deque Blocks; + std::deque Shapes; + Shape *Root; + + Relooper(); + ~Relooper(); + + void AddBlock(Block *New); + + // Calculates the shapes + void Calculate(Block *Entry); + + // Renders the result. + void Render(); + + // Sets the global buffer all printing goes to. Must call this or MakeOutputBuffer. + static void SetOutputBuffer(char *Buffer, int Size); + + // Creates an output buffer. Must call this or SetOutputBuffer. + static void MakeOutputBuffer(int Size); +}; + +typedef std::set BlockSet; +typedef std::map BlockBlockSetMap; + +#if DEBUG +struct Debugging { + static void Dump(BlockSet &Blocks, const char *prefix=NULL); +}; +#endif + +#endif // __cplusplus + +// C API - useful for binding to other languages + +#ifdef _WIN32 + #ifdef RELOOPERDLL_EXPORTS + #define RELOOPERDLL_API __declspec(dllexport) + #else + #define RELOOPERDLL_API __declspec(dllimport) + #endif +#else + #define RELOOPERDLL_API +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +RELOOPERDLL_API void rl_set_output_buffer(char *buffer, int size); +RELOOPERDLL_API void rl_make_output_buffer(int size); +RELOOPERDLL_API void *rl_new_block(const char *text); +RELOOPERDLL_API void rl_delete_block(void *block); +RELOOPERDLL_API void rl_block_add_branch_to(void *from, void *to, const char *condition, const char *code); +RELOOPERDLL_API void *rl_new_relooper(); +RELOOPERDLL_API void rl_delete_relooper(void *relooper); +RELOOPERDLL_API void rl_relooper_add_block(void *relooper, void *block); +RELOOPERDLL_API void rl_relooper_calculate(void *relooper, void *entry); +RELOOPERDLL_API void rl_relooper_render(void *relooper); + +#ifdef __cplusplus +} +#endif + diff --git a/src/relooper/doit.sh b/src/relooper/doit.sh new file mode 100755 index 0000000000000..bf2683d57a6a0 --- /dev/null +++ b/src/relooper/doit.sh @@ -0,0 +1,68 @@ +echo "relooper" +g++ Relooper.cpp -c -g +g++ Relooper.cpp -c -g -DDEBUG -o RelooperDebug.o + +echo "test" +g++ test.cpp -c -o test.o -g +g++ Relooper.o test.o -o test + +echo "test 2" +gcc test2.c -c -o test2.o -g +g++ Relooper.o test2.o -o test2 + +echo "test 3" +gcc test3.c -c -o test3.o -g +g++ Relooper.o test3.o -o test3 + +echo "test debug" +gcc test_debug.cpp -c -o test_debug.o -g -DDEBUG +g++ RelooperDebug.o test_debug.o -o test_debug + +echo "test dead" +gcc test_dead.cpp -c -o test_dead.o -g +g++ Relooper.o test_dead.o -o test_dead + +echo "test 4" +g++ test4.cpp -c -o test4.o -g +g++ Relooper.o test4.o -o test4 + +echo "test 5" +g++ test5.cpp -c -o test5.o -g +g++ Relooper.o test5.o -o test5 + +echo "test 6" +g++ test6.cpp -c -o test6.o -g +g++ Relooper.o test6.o -o test6 + +echo "test inf" +g++ test_inf.cpp -c -o test_inf.o -g +g++ Relooper.o test_inf.o -o test_inf + +echo "test fuzz1" +g++ test_fuzz1.cpp -c -o test_fuzz1.o -g +g++ Relooper.o test_fuzz1.o -o test_fuzz1 + +echo "test fuzz2" +g++ test_fuzz2.cpp -c -o test_fuzz2.o -g +g++ Relooper.o test_fuzz2.o -o test_fuzz2 + +echo "test fuzz3" +g++ test_fuzz3.cpp -c -o test_fuzz3.o -g +g++ Relooper.o test_fuzz3.o -o test_fuzz3 + +echo "test fuzz4" +g++ test_fuzz4.cpp -c -o test_fuzz4.o -g +g++ Relooper.o test_fuzz4.o -o test_fuzz4 + +echo "test fuzz5" +g++ test_fuzz5.cpp -c -o test_fuzz5.o -g +g++ Relooper.o test_fuzz5.o -o test_fuzz5 + +echo "test fuzz6" +g++ test_fuzz6.cpp -c -o test_fuzz6.o -g +g++ Relooper.o test_fuzz6.o -o test_fuzz6 + +echo +echo "=============================" +echo + diff --git a/src/relooper/emscripten/Makefile b/src/relooper/emscripten/Makefile new file mode 100644 index 0000000000000..277dd5388d77e --- /dev/null +++ b/src/relooper/emscripten/Makefile @@ -0,0 +1,18 @@ +EMSCRIPTEN = ~/Dev/emscripten +EMCC = $(EMSCRIPTEN)/emcc +BINDINGS_GENERATOR = $(EMSCRIPTEN)/tools/bindings_generator.py +NATIVIZER = $(EMSCRIPTEN)/tools/nativize_llvm.py + +all: relooper.js + +relooper.js: + $(EMCC) -O2 ../Relooper.cpp -I.. --post-js glue.js -o relooper.raw.js -s TOTAL_MEMORY=52428800 -s DEFAULT_LIBRARY_FUNCS_TO_INCLUDE='["memcpy", "memset", "malloc", "free", "puts"]' + echo "// Relooper, (C) 2012 Alon Zakai, MIT license, https://github.com/kripken/Relooper" > relooper.js + echo "var Relooper = (function() {" >> relooper.js + cat relooper.raw.js >> relooper.js + echo " return Module.Relooper;" >> relooper.js + echo "})();" >> relooper.js + +clean: + rm relooper.js + diff --git a/src/relooper/emscripten/glue.js b/src/relooper/emscripten/glue.js new file mode 100644 index 0000000000000..15998acf2c55b --- /dev/null +++ b/src/relooper/emscripten/glue.js @@ -0,0 +1,54 @@ + + var RBUFFER_SIZE = 20*1024*1024; + var rbuffer = _malloc(RBUFFER_SIZE); + _rl_set_output_buffer(rbuffer, RBUFFER_SIZE); + + var TBUFFER_SIZE = 10*1024*1024; + var tbuffer = _malloc(TBUFFER_SIZE); + + var RelooperGlue = {}; + RelooperGlue['init'] = function() { + this.r = _rl_new_relooper(); + }, + RelooperGlue['addBlock'] = function(text) { + assert(this.r); + assert(text.length+1 < TBUFFER_SIZE); + writeStringToMemory(text, tbuffer); + var b = _rl_new_block(tbuffer); + _rl_relooper_add_block(this.r, b); + return b; + }; + RelooperGlue['addBranch'] = function(from, to, condition, code) { + assert(this.r); + if (condition) { + assert(condition.length+1 < TBUFFER_SIZE/2); + writeStringToMemory(condition, tbuffer); + condition = tbuffer; + } else { + condition = 0; // allow undefined, null, etc. as inputs + } + if (code) { + assert(code.length+1 < TBUFFER_SIZE/2); + writeStringToMemory(code, tbuffer + TBUFFER_SIZE/2); + code = tbuffer + TBUFFER_SIZE/2; + } else { + code = 0; // allow undefined, null, etc. as inputs + } + _rl_block_add_branch_to(from, to, condition, code); + }; + RelooperGlue['render'] = function(entry) { + assert(this.r); + assert(entry); + _rl_relooper_calculate(this.r, entry); + _rl_relooper_render(this.r); + var ret = Pointer_stringify(rbuffer); + _rl_delete_relooper(this.r); + this.r = 0; + return ret; + }; + RelooperGlue['setDebug'] = function(debug) { + _rl_set_debugging(+!!debug); + }; + + Module['Relooper'] = RelooperGlue; + diff --git a/src/relooper/emscripten/test.js b/src/relooper/emscripten/test.js new file mode 100644 index 0000000000000..c408a9122d619 --- /dev/null +++ b/src/relooper/emscripten/test.js @@ -0,0 +1,44 @@ +// js -m -n -e "load('relooper.js')" test.js + +function test() { + print("-- If shape --\n"); + + //Relooper.setDebug(1); + + { + Relooper.init(); + + var b_a = Relooper.addBlock("// block A\n"); + var b_b = Relooper.addBlock("// block B\n"); + var b_c = Relooper.addBlock("// block C\n"); + + Relooper.addBranch(b_a, b_b, "check == 10", "atob();"); + Relooper.addBranch(b_a, b_c, 0, "atoc();"); + + Relooper.addBranch(b_b, b_c, 0, "btoc();"); + + var output = Relooper.render(b_a); + print(output); + } + + { + Relooper.init(); + + var b_a = Relooper.addBlock("// block A\n"); + var b_b = Relooper.addBlock("// block B\n"); + var b_c = Relooper.addBlock("// block C\n"); + + Relooper.addBranch(b_a, b_b, "check == fee()"); + Relooper.addBranch(b_a, b_c, 0, 0); + + Relooper.addBranch(b_c, b_b); + + var output = Relooper.render(b_a); + print(output); + } +} + +test(); + +// TODO: wrap the relooper itself + diff --git a/src/relooper/fuzzer.py b/src/relooper/fuzzer.py new file mode 100644 index 0000000000000..887eab3b4d1c1 --- /dev/null +++ b/src/relooper/fuzzer.py @@ -0,0 +1,116 @@ + +import random, subprocess, difflib + +while True: + # Random decisions + num = random.randint(2, 250) + density = random.random() * random.random() + decisions = [random.randint(1, num*20) for x in range(num*3)] + branches = [0]*num + defaults = [0]*num + for i in range(num): + b = set([]) + bs = random.randint(1, max(1, round(density*random.random()*(num-1)))) + for j in range(bs): + b.add(random.randint(1, num-1)) + b = list(b) + defaults[i] = random.choice(b) + b.remove(defaults[i]) + branches[i] = b + print num, density + + for temp in ['fuzz', 'fuzz.fast.js', 'fuzz.slow.js', 'fuzz.cpp']: + try: + os.unlink(temp) + except: + pass + + # parts + entry = '''print('entry'); var label; var state; var decisions = %s; var index = 0; function check() { if (index == decisions.length) throw 'HALT'; return decisions[index++] }''' % str(decisions) + + slow = entry + '\n' + for i in range(len(branches[0])): + if i > 0: slow += 'else ' + b = branches[0] + slow += 'if (state %% %d == %d) { label = %d; }\n' % (len(b)+1, i, b[i]) # TODO: split range 1-n into these options + if len(branches[0]): slow += 'else ' + slow += 'label = %d;\n' % defaults[0] + + slow += ''' +while(1) switch(label) { +''' + + fast = ''' + +#include +#include "Relooper.h" + +int main() { + char *buffer = (char*)malloc(10*1024*1024); + Relooper::SetOutputBuffer(buffer, 10*1024*1024); +''' + + for i in range(1, num): + slow += ' case %d: print(%d); state = check(); \n' % (i, i) + b = branches[i] + for j in range(len(b)): + slow += ' if (state %% %d == %d) { label = %d; break }\n' % (len(b)+1, j, b[j]) # TODO: split range 1-n into these options + slow += ' label = %d; break\n' % defaults[i] + + for i in range(num): + if i == 0: + fast += ''' + Block *b%d = new Block("%s"); +''' % (i, entry) + else: + fast += ''' Block *b%d = new Block("print(%d); state = check();%s"); +''' % (i, i, '// ' + ('.' * int(random.expovariate(0.5/num)))) + + for i in range(num): + b = branches[i] + for j in range(len(b)): + fast += ''' b%d->AddBranchTo(b%d, "state %% %d == %d"); +''' % (i, b[j], len(b)+1, j) + fast += ''' b%d->AddBranchTo(b%d, NULL); +''' % (i, defaults[i]) + + fast += ''' + Relooper r; +''' + + for i in range(num): + fast += ''' r.AddBlock(b%d); +''' % i + + fast += ''' + r.Calculate(b0); + printf("\\n\\n"); + r.Render(); + + puts(buffer); + + return 1; +} +''' + + slow += '}' + + open('fuzz.slow.js', 'w').write(slow) + open('fuzz.cpp', 'w').write(fast) + print '_' + slow_out = subprocess.Popen(['/home/alon/Dev/mozilla-central/js/src/fast/js', '-m', '-n', 'fuzz.slow.js'], stdout=subprocess.PIPE).communicate()[0] + + print '.' + subprocess.call(['g++', 'fuzz.cpp', 'Relooper.o', '-o', 'fuzz', '-g']) + print '*' + subprocess.call(['./fuzz'], stdout=open('fuzz.fast.js', 'w')) + print '-' + fast_out = subprocess.Popen(['/home/alon/Dev/mozilla-central/js/src/fast/js', '-m', '-n', 'fuzz.fast.js'], stdout=subprocess.PIPE).communicate()[0] + print + + if slow_out != fast_out: + print ''.join([a.rstrip()+'\n' for a in difflib.unified_diff(slow_out.split('\n'), fast_out.split('\n'), fromfile='slow', tofile='fast')]) + assert False + + #break + diff --git a/src/relooper/ministring.h b/src/relooper/ministring.h new file mode 100644 index 0000000000000..d0f042c80862d --- /dev/null +++ b/src/relooper/ministring.h @@ -0,0 +1,35 @@ + +// Tiny implementation of strings. Avoids linking in all of std::string + +#include +#include + +class ministring { + int used; + char *buffer; + int bufferSize; +public: + ministring() : used(0), buffer(NULL), bufferSize(0) {} + ~ministring() { if (buffer) free(buffer); } + + char *c_str() { return buffer; } + int size() { return used; } + + void clear() { + used = 0; // keep the buffer alive as an optimization, just resize + } + + ministring& operator+=(const char *s) { + int len = strlen(s); + if (used + len + 2 > bufferSize) { + // try to avoid frequent reallocations + bufferSize = 2*(bufferSize + len); + bufferSize += 1024 - bufferSize % 1024; + buffer = (char*)(buffer ? realloc(buffer, bufferSize) : malloc(bufferSize)); + } + strcpy(buffer + used, s); + used += len; + return *this; + } +}; + diff --git a/src/relooper/paper.pdf b/src/relooper/paper.pdf new file mode 100644 index 0000000000000000000000000000000000000000..401162ace904828daf6f39fedc8217f6ec5551d1 GIT binary patch literal 220318 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

uK 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 literal 0 HcmV?d00001 diff --git a/src/relooper/test.cpp b/src/relooper/test.cpp new file mode 100644 index 0000000000000..0d029216b2bf1 --- /dev/null +++ b/src/relooper/test.cpp @@ -0,0 +1,195 @@ + +#include "Relooper.h" + +int main() { + char buffer[10000]; + + if (1) { + Relooper::SetOutputBuffer(buffer, sizeof(buffer)); + + printf("\n\n-- If pattern --\n\n"); + + Block *b_a = new Block("// block A\n"); + Block *b_b = new Block("// block B\n"); + Block *b_c = new Block("// block C\n"); + + b_a->AddBranchTo(b_b, "check == 10", "atob();"); + b_a->AddBranchTo(b_c, NULL, "atoc();"); + + b_b->AddBranchTo(b_c, NULL, "btoc();"); + + Relooper r; + r.AddBlock(b_a); + r.AddBlock(b_b); + r.AddBlock(b_c); + + r.Calculate(b_a); + printf("\n\n"); + r.Render(); + + puts(buffer); + } + + if (1) { + Relooper::SetOutputBuffer(buffer, sizeof(buffer)); + + printf("\n\n-- If-else pattern --\n\n"); + + Block *b_a = new Block("// block A\n"); + Block *b_b = new Block("// block B\n"); + Block *b_c = new Block("// block C\n"); + Block *b_d = new Block("// block D\n"); + + b_a->AddBranchTo(b_b, "check == 15"); + b_a->AddBranchTo(b_c, NULL); + + b_b->AddBranchTo(b_d, NULL); + + b_c->AddBranchTo(b_d, NULL); + + Relooper r; + r.AddBlock(b_a); + r.AddBlock(b_b); + r.AddBlock(b_c); + r.AddBlock(b_d); + + r.Calculate(b_a); + printf("\n\n"); + r.Render(); + + puts(buffer); + } + + if (1) { + Relooper::SetOutputBuffer(buffer, sizeof(buffer)); + + printf("\n\n-- Loop + tail pattern --\n\n"); + + Block *b_a = new Block("// block A\nvar check = maybe();\n"); + Block *b_b = new Block("// block B\n"); + Block *b_c = new Block("// block C\n"); + + b_a->AddBranchTo(b_b, NULL); + + b_b->AddBranchTo(b_a, "check == 41"); + b_b->AddBranchTo(b_c, NULL); + + Relooper r; + r.AddBlock(b_a); + r.AddBlock(b_b); + r.AddBlock(b_c); + + r.Calculate(b_a); + printf("\n\n"); + r.Render(); + + puts(buffer); + } + + if (1) { + Relooper::SetOutputBuffer(buffer, sizeof(buffer)); + + printf("\n\n-- Loop with phi to head \n\n"); + + void *block_map[10000]; + void *rl = rl_new_relooper(); + void *b1 = rl_new_block("// code 1"); + block_map[1] = b1; + rl_relooper_add_block(rl, block_map[1]); + void *b2 = rl_new_block("// code 2"); + block_map[2] = b2; + rl_relooper_add_block(rl, block_map[2]); + void *b3 = rl_new_block("// code 3"); + block_map[3] = b3; + rl_relooper_add_block(rl, block_map[3]); + void *b4 = rl_new_block("// code 4"); + block_map[4] = b4; + rl_relooper_add_block(rl, block_map[4]); + void *b5 = rl_new_block("// code 5"); + block_map[5] = b5; + rl_relooper_add_block(rl, block_map[5]); + void *b6 = rl_new_block("// code 6"); + block_map[6] = b6; + rl_relooper_add_block(rl, block_map[6]); + void *b7 = rl_new_block("// code 7"); + block_map[7] = b7; + rl_relooper_add_block(rl, block_map[7]); + rl_block_add_branch_to(block_map[1], block_map[2], NULL, "var $i_0 = 0;var $x_0 = 5; "); + rl_block_add_branch_to(block_map[2], block_map[3], "$2", NULL); + rl_block_add_branch_to(block_map[2], block_map[7], NULL, "var $x_1 = $x_0; "); + rl_block_add_branch_to(block_map[3], block_map[4], "$6", NULL); + rl_block_add_branch_to(block_map[3], block_map[2], NULL, "var $i_0 = $7;var $x_0 = $5; "); + rl_block_add_branch_to(block_map[4], block_map[5], "$10", NULL); + rl_block_add_branch_to(block_map[4], block_map[6], NULL, NULL); + rl_block_add_branch_to(block_map[5], block_map[6], NULL, NULL); + rl_block_add_branch_to(block_map[6], block_map[7], NULL, "var $x_1 = $13; "); + rl_relooper_calculate(rl, block_map[1]); + rl_relooper_render(rl); + rl_delete_relooper(rl); + puts(buffer); + } + + if (1) { + Relooper::SetOutputBuffer(buffer, sizeof(buffer)); + + printf("\n\n-- phi on split dead ends --\n\n"); + + Block *b_a = new Block("// block A...................................................................................................\n"); + Block *b_b = new Block("// block B...................................................................................................\n"); + Block *b_c = new Block("// block C...................................................................................................\n"); + Block *b_d = new Block("// block D\n"); // small and splittable! + Block *b_e = new Block("// block E\n"); + + b_a->AddBranchTo(b_b, "chak()", "atob();"); + b_a->AddBranchTo(b_c, NULL, "atoc();"); + + b_b->AddBranchTo(b_d, NULL, "btod();"); + + b_c->AddBranchTo(b_d, NULL, "ctod2();"); + + Relooper r; + r.AddBlock(b_a); + r.AddBlock(b_b); + r.AddBlock(b_c); + r.AddBlock(b_d); + r.AddBlock(b_e); + + r.Calculate(b_a); + printf("\n\n"); + r.Render(); + + puts(buffer); + } +/* + if (1) { + Relooper::SetOutputBuffer(buffer, sizeof(buffer)); + + printf("\n\n-- Unbalanced with a dead end --\n\n"); + + Block *b_a = new Block("// block A\n"); + Block *b_b = new Block("// block B\n"); + Block *b_c = new Block("// block C\n"); + Block *b_d = new Block("// block D\n"); + + b_a->AddBranchTo(b_b, "check == 10"); + b_a->AddBranchTo(b_c, NULL); + + b_b->AddBranchTo(b_d, NULL); + + b_d->AddBranchTo(b_b, NULL); + + Relooper r; + r.AddBlock(b_a); + r.AddBlock(b_b); + r.AddBlock(b_c); + r.AddBlock(b_d); + + r.Calculate(b_a); + printf("\n\n"); + r.Render(); + + puts(buffer); + } +*/ +} + diff --git a/src/relooper/test.txt b/src/relooper/test.txt new file mode 100644 index 0000000000000..ff4ada2455925 --- /dev/null +++ b/src/relooper/test.txt @@ -0,0 +1,99 @@ + + +-- If pattern -- + + + +// block A +if (check == 10) { + atob(); + // block B + btoc(); +} else { + atoc(); +} +// block C + + + +-- If-else pattern -- + + + +// block A +if (check == 15) { + // block B +} else { + // block C +} +// block D + + + +-- Loop + tail pattern -- + + + +while(1) { + // block A + var check = maybe(); + // block B + if (!(check == 41)) { + break; + } +} +// block C + + + +-- Loop with phi to head + +// code 1 +var $i_0 = 0;var $x_0 = 5; +while(1) { + // code 2 + if (!($2)) { + var $x_1 = $x_0; + label = 18; + break; + } + // code 3 + if ($6) { + label = 14; + break; + } else { + var $i_0 = $7;var $x_0 = $5; + } +} +if (label == 14) { + // code 4 + if ($10) { + // code 5 + } + // code 6 + var $x_1 = $13; + // code 7 +} +else if (label == 18) { + // code 7 +} + + + +-- phi on split dead ends -- + + + +// block A................................................................................................... +if (chak()) { + atob(); + // block B................................................................................................... + btod(); + // block D +} else { + atoc(); + // block C................................................................................................... + ctod2(); + // block D +} + diff --git a/src/relooper/test2.c b/src/relooper/test2.c new file mode 100644 index 0000000000000..118a2627f60cd --- /dev/null +++ b/src/relooper/test2.c @@ -0,0 +1,44 @@ + +#include "Relooper.h" + +int main() { + char buffer[10000]; + rl_set_output_buffer(buffer, sizeof(buffer)); + + void *r = rl_new_relooper(); + void *ep = rl_new_block("ep"); + rl_relooper_add_block(r, ep); + void *LBB1 = rl_new_block("LBB1"); + rl_relooper_add_block(r, LBB1); + void *LBB2 = rl_new_block("LBB2"); + rl_relooper_add_block(r, LBB2); + void *LBB3 = rl_new_block("LBB3"); + rl_relooper_add_block(r, LBB3); +/* + void *LBB4 = rl_new_block("LBB4"); + rl_relooper_add_block(r, LBB4); + void *LBB5 = rl_new_block("LBB5"); + rl_relooper_add_block(r, LBB5); + void *LBB6 = rl_new_block("LBB6"); + rl_relooper_add_block(r, LBB6); +*/ + rl_block_add_branch_to(ep, LBB1, "ep -> LBB1", NULL); + rl_block_add_branch_to(ep, LBB3, NULL, NULL); + rl_block_add_branch_to(LBB1, LBB2, "LBB1 -> LBB2", NULL); + rl_block_add_branch_to(LBB1, LBB3, NULL, NULL); + rl_block_add_branch_to(LBB2, LBB3, NULL, NULL); +// rl_block_add_branch_to(LBB3, LBB4, "LBB3 -> LBB4"); +// rl_block_add_branch_to(LBB3, LBB6, "LBB3 -> LBB6"); +/* + rl_block_add_branch_to(LBB4, LBB5, "LBB4 -> LBB5"); + rl_block_add_branch_to(LBB4, LBB6, "LBB4 -> LBB6"); + rl_block_add_branch_to(LBB5, LBB6, "LBB5 -> LBB6"); + rl_block_add_branch_to(LBB5, LBB5, "LBB5 -> LBB5"); +*/ + rl_relooper_calculate(r, ep); + rl_relooper_render(r); + rl_delete_relooper(r); + + puts(buffer); +} + diff --git a/src/relooper/test2.txt b/src/relooper/test2.txt new file mode 100644 index 0000000000000..c77ce49128361 --- /dev/null +++ b/src/relooper/test2.txt @@ -0,0 +1,12 @@ +ep +do { + if (ep -> LBB1) { + LBB1 + if (!(LBB1 -> LBB2)) { + break; + } + LBB2 + } +} while(0); +LBB3 + diff --git a/src/relooper/test3.c b/src/relooper/test3.c new file mode 100644 index 0000000000000..2cef14fbaaa7a --- /dev/null +++ b/src/relooper/test3.c @@ -0,0 +1,42 @@ + +#include "Relooper.h" + +int main() { + char buffer[10000]; + rl_set_output_buffer(buffer, sizeof(buffer)); + + void *r = rl_new_relooper(); + void *ep = rl_new_block("ep"); + rl_relooper_add_block(r, ep); + void *LBB1 = rl_new_block("LBB1"); + rl_relooper_add_block(r, LBB1); + void *LBB2 = rl_new_block("LBB2"); + rl_relooper_add_block(r, LBB2); + void *LBB3 = rl_new_block("LBB3"); + rl_relooper_add_block(r, LBB3); + void *LBB4 = rl_new_block("LBB4"); + rl_relooper_add_block(r, LBB4); + void *LBB5 = rl_new_block("LBB5"); + rl_relooper_add_block(r, LBB5); + void *LBB6 = rl_new_block("LBB6"); + rl_relooper_add_block(r, LBB6); + + rl_block_add_branch_to(ep, LBB1, "ep -> LBB1", NULL); + rl_block_add_branch_to(ep, LBB3, NULL, NULL); + rl_block_add_branch_to(LBB1, LBB2, "LBB1 -> LBB2", NULL); + rl_block_add_branch_to(LBB1, LBB3, NULL, NULL); + rl_block_add_branch_to(LBB2, LBB3, NULL, NULL); + rl_block_add_branch_to(LBB3, LBB4, "LBB3 -> LBB4", NULL); + rl_block_add_branch_to(LBB3, LBB6, NULL, NULL); + rl_block_add_branch_to(LBB4, LBB5, "LBB4 -> LBB5", NULL); + rl_block_add_branch_to(LBB4, LBB6, NULL, NULL); + rl_block_add_branch_to(LBB5, LBB6, "LBB5 -> LBB6", NULL); + rl_block_add_branch_to(LBB5, LBB5, NULL, NULL); + + rl_relooper_calculate(r, ep); + rl_relooper_render(r); + rl_delete_relooper(r); + + puts(buffer); +} + diff --git a/src/relooper/test3.txt b/src/relooper/test3.txt new file mode 100644 index 0000000000000..696542ef98610 --- /dev/null +++ b/src/relooper/test3.txt @@ -0,0 +1,27 @@ +ep +do { + if (ep -> LBB1) { + LBB1 + if (!(LBB1 -> LBB2)) { + break; + } + LBB2 + } +} while(0); +LBB3 +L5: do { + if (LBB3 -> LBB4) { + LBB4 + if (!(LBB4 -> LBB5)) { + break; + } + while(1) { + LBB5 + if (LBB5 -> LBB6) { + break L5; + } + } + } +} while(0); +LBB6 + diff --git a/src/relooper/test4.cpp b/src/relooper/test4.cpp new file mode 100644 index 0000000000000..76fc8ec066580 --- /dev/null +++ b/src/relooper/test4.cpp @@ -0,0 +1,40 @@ + +#include "Relooper.h" + +int main() { + char buffer[10000]; + rl_set_output_buffer(buffer, sizeof(buffer)); + + void *r = rl_new_relooper(); + + void *b19 = rl_new_block("//19"); + rl_relooper_add_block(r, b19); + void *b20 = rl_new_block("//20"); + rl_relooper_add_block(r, b20); + void *b21 = rl_new_block("//21"); + rl_relooper_add_block(r, b21); + void *b22 = rl_new_block("//22"); + rl_relooper_add_block(r, b22); + void *b23 = rl_new_block("//23"); + rl_relooper_add_block(r, b23); + void *b24 = rl_new_block("//24"); + rl_relooper_add_block(r, b24); + void *b28 = rl_new_block("//28"); + rl_relooper_add_block(r, b28); + + rl_block_add_branch_to(b19, b20, " 1 ", NULL); + rl_block_add_branch_to(b19, b22, NULL, NULL); + rl_block_add_branch_to(b20, b21, " 1 ", NULL); + rl_block_add_branch_to(b20, b22, NULL, NULL); + rl_block_add_branch_to(b21, b23, NULL, NULL); + rl_block_add_branch_to(b22, b23, NULL, NULL); + rl_block_add_branch_to(b23, b24, " 1 ", NULL); + rl_block_add_branch_to(b23, b28, NULL, NULL); + + rl_relooper_calculate(r, b19); + rl_relooper_render(r); + rl_delete_relooper(r); + + puts(buffer); +} + diff --git a/src/relooper/test4.txt b/src/relooper/test4.txt new file mode 100644 index 0000000000000..f0bfb9729dac9 --- /dev/null +++ b/src/relooper/test4.txt @@ -0,0 +1,24 @@ +//19 +do { + if ( 1 ) { + //20 + if (!( 1 )) { + label = 4; + break; + } + //21 + break; + } else { + label = 4; + } +} while(0); +if (label == 4) { + //22 +} +//23 +if ( 1 ) { + //24 +} else { + //28 +} + diff --git a/src/relooper/test5.cpp b/src/relooper/test5.cpp new file mode 100644 index 0000000000000..f86da2b3cd68d --- /dev/null +++ b/src/relooper/test5.cpp @@ -0,0 +1,40 @@ + +#include "Relooper.h" + +int main() { + char buffer[10000]; + rl_set_output_buffer(buffer, sizeof(buffer)); + + void *r = rl_new_relooper(); + + void *b0 = rl_new_block("//0"); + rl_relooper_add_block(r, b0); + void *b1 = rl_new_block("//1"); + rl_relooper_add_block(r, b1); + void *b2 = rl_new_block("//2"); + rl_relooper_add_block(r, b2); + void *b3 = rl_new_block("//3"); + rl_relooper_add_block(r, b3); + void *b4 = rl_new_block("//4"); + rl_relooper_add_block(r, b4); + void *b5 = rl_new_block("//5"); + rl_relooper_add_block(r, b5); + + rl_block_add_branch_to(b0, b1, "check(0)", NULL); + rl_block_add_branch_to(b0, b4, NULL, "goingFrom0to4();"); + rl_block_add_branch_to(b1, b1, "check(1)", NULL); + rl_block_add_branch_to(b1, b2, NULL, NULL); + rl_block_add_branch_to(b2, b2, "check(2)", NULL); + rl_block_add_branch_to(b2, b3, NULL, NULL); + rl_block_add_branch_to(b4, b4, "check(4)", NULL); + rl_block_add_branch_to(b4, b5, NULL, NULL); + rl_block_add_branch_to(b5, b3, "check(5)", NULL); + rl_block_add_branch_to(b5, b5, NULL, NULL); + + rl_relooper_calculate(r, b0); + rl_relooper_render(r); + rl_delete_relooper(r); + + puts(buffer); +} + diff --git a/src/relooper/test5.txt b/src/relooper/test5.txt new file mode 100644 index 0000000000000..ad769ae7bb0b3 --- /dev/null +++ b/src/relooper/test5.txt @@ -0,0 +1,32 @@ +//0 +if (check(0)) { + while(1) { + //1 + if (!(check(1))) { + break; + } + } + while(1) { + //2 + if (!(check(2))) { + break; + } + } + //3 +} else { + goingFrom0to4(); + while(1) { + //4 + if (!(check(4))) { + break; + } + } + while(1) { + //5 + if (check(5)) { + break; + } + } + //3 +} + diff --git a/src/relooper/test6.cpp b/src/relooper/test6.cpp new file mode 100644 index 0000000000000..90453d4c70b95 --- /dev/null +++ b/src/relooper/test6.cpp @@ -0,0 +1,31 @@ + +#include "Relooper.h" + +int main() { + char buffer[10000]; + rl_set_output_buffer(buffer, sizeof(buffer)); + + void *r = rl_new_relooper(); + + void *b0 = rl_new_block("//0"); + rl_relooper_add_block(r, b0); + void *b1 = rl_new_block("//1"); + rl_relooper_add_block(r, b1); + void *b2 = rl_new_block("//2"); + rl_relooper_add_block(r, b2); + void *b3 = rl_new_block("//3"); + rl_relooper_add_block(r, b3); + + rl_block_add_branch_to(b0, b1, "check(0)", NULL); + rl_block_add_branch_to(b0, b3, NULL, NULL); + rl_block_add_branch_to(b1, b2, "check(1)", NULL); + rl_block_add_branch_to(b1, b3, NULL, NULL); + rl_block_add_branch_to(b2, b3, NULL, NULL); + + rl_relooper_calculate(r, b0); + rl_relooper_render(r); + rl_delete_relooper(r); + + puts(buffer); +} + diff --git a/src/relooper/test6.txt b/src/relooper/test6.txt new file mode 100644 index 0000000000000..c5effd0887043 --- /dev/null +++ b/src/relooper/test6.txt @@ -0,0 +1,12 @@ +//0 +do { + if (check(0)) { + //1 + if (!(check(1))) { + break; + } + //2 + } +} while(0); +//3 + diff --git a/src/relooper/test_dead.cpp b/src/relooper/test_dead.cpp new file mode 100644 index 0000000000000..887d254c6859f --- /dev/null +++ b/src/relooper/test_dead.cpp @@ -0,0 +1,28 @@ + +#include "Relooper.h" + +int main() { + char buffer[10000]; + + Relooper::SetOutputBuffer(buffer, sizeof(buffer)); + + printf("\n\n-- If pattern --\n\n"); + + Block *b_a = new Block("// block A\n"); + Block *b_b = new Block("// block B\n"); // never reached + + b_b->AddBranchTo(b_b, NULL); + + Relooper r; + r.AddBlock(b_a); + r.AddBlock(b_b); + + r.Calculate(b_a); + printf("\n\n"); + r.Render(); + + puts(buffer); + + printf("I did not crash even though I have dead code with a branch!\n"); +} + diff --git a/src/relooper/test_dead.txt b/src/relooper/test_dead.txt new file mode 100644 index 0000000000000..ae54e2cda819b --- /dev/null +++ b/src/relooper/test_dead.txt @@ -0,0 +1,9 @@ + + +-- If pattern -- + + + +// block A + +I did not crash even though I have dead code with a branch! diff --git a/src/relooper/test_debug.cpp b/src/relooper/test_debug.cpp new file mode 100644 index 0000000000000..14511b625cbab --- /dev/null +++ b/src/relooper/test_debug.cpp @@ -0,0 +1,30 @@ + +#include "Relooper.h" + +int main() { + char buffer[10000]; + rl_set_output_buffer(buffer, sizeof(buffer)); + + void *r = rl_new_relooper(); + void *ep = rl_new_block("ep"); + rl_relooper_add_block(r, ep); + void *LBB1 = rl_new_block("LBB1"); + rl_relooper_add_block(r, LBB1); + void *LBB2 = rl_new_block("LBB2"); + rl_relooper_add_block(r, LBB2); + void *LBB3 = rl_new_block("LBB3"); + rl_relooper_add_block(r, LBB3); + + rl_block_add_branch_to(ep, LBB1, "ep -> LBB1", NULL); + rl_block_add_branch_to(ep, LBB3, NULL, NULL); + rl_block_add_branch_to(LBB1, LBB2, "LBB1 -> LBB2", NULL); + rl_block_add_branch_to(LBB1, LBB3, NULL, NULL); + rl_block_add_branch_to(LBB2, LBB3, NULL, NULL); + + rl_relooper_calculate(r, ep); + rl_relooper_render(r); + rl_delete_relooper(r); + + puts(buffer); +} + diff --git a/src/relooper/test_debug.txt b/src/relooper/test_debug.txt new file mode 100644 index 0000000000000..1c7d05089f7a5 --- /dev/null +++ b/src/relooper/test_debug.txt @@ -0,0 +1,96 @@ +#include "Relooper.h" +int main() { + char buffer[100000]; + rl_set_output_buffer(buffer); + void *block_map[10000]; + void *rl = rl_new_relooper(); + void *b1 = rl_new_block("// code 1"); + block_map[1] = b1; + rl_relooper_add_block(rl, block_map[1]); + void *b2 = rl_new_block("// code 2"); + block_map[2] = b2; + rl_relooper_add_block(rl, block_map[2]); + void *b3 = rl_new_block("// code 3"); + block_map[3] = b3; + rl_relooper_add_block(rl, block_map[3]); + void *b4 = rl_new_block("// code 4"); + block_map[4] = b4; + rl_relooper_add_block(rl, block_map[4]); + rl_block_add_branch_to(block_map[1], block_map[2], "ep -> LBB1", NULL); + rl_block_add_branch_to(block_map[1], block_map[4], NULL, NULL); + rl_block_add_branch_to(block_map[2], block_map[3], "LBB1 -> LBB2", NULL); + rl_block_add_branch_to(block_map[2], block_map[4], NULL, NULL); + rl_block_add_branch_to(block_map[3], block_map[4], NULL, NULL); + rl_relooper_calculate(rl, block_map[1]); + rl_relooper_render(rl); + rl_delete_relooper(rl); + puts(buffer); + return 0; +} +// Adding block 1 (ep) +// with branch out to 2 +// with branch out to 4 +// Adding block 2 (LBB1) +// with branch out to 3 +// with branch out to 4 +// Adding block 3 (LBB2) +// with branch out to 4 +// Adding block 4 (LBB3) +// Process() called +// Process() running + blocks : 1 2 3 4 + entries: 1 +// creating simple block with block #1 +// Solipsizing branches into 2 + relevant to solipsize: 1 +// eliminated branch from 1 +// Solipsizing branches into 4 + relevant to solipsize: 1 +// eliminated branch from 1 +// Process() running + blocks : 2 3 4 + entries: 2 4 +// Investigated independent groups: + group: 2 3 +// Independent groups: 1 +// Handleable independent groups: 1 +// creating multiple block with 1 inner groups +// multiple group with entry 2: + 2 3 +// Solipsizing branches into 4 + relevant to solipsize: 2 3 +// eliminated branch from 2 +// eliminated branch from 3 +// Process() called +// Process() running + blocks : 2 3 + entries: 2 +// creating simple block with block #2 +// Solipsizing branches into 3 + relevant to solipsize: 2 +// eliminated branch from 2 +// Process() running + blocks : 3 + entries: 3 +// creating simple block with block #3 +// Process() returning + remaining blocks after multiple: 4 +// Process() running + blocks : 4 + entries: 4 +// creating simple block with block #4 +// Process() returning +// === Optimizing shapes === +// Fusing Multiple to Simple +ep +do { + if (ep -> LBB1) { + LBB1 + if (!(LBB1 -> LBB2)) { + break; + } + LBB2 + } +} while(0); +LBB3 + diff --git a/src/relooper/test_fuzz1.cpp b/src/relooper/test_fuzz1.cpp new file mode 100644 index 0000000000000..542056947221b --- /dev/null +++ b/src/relooper/test_fuzz1.cpp @@ -0,0 +1,52 @@ + + +#include +#include "Relooper.h" + +int main() { + #define SIZE (10*1024*1024) + char *buffer = (char*)malloc(SIZE); + Relooper::SetOutputBuffer(buffer, SIZE); + + Block *b0 = new Block("print('entry'); var label; var state; var decisions = [4, 1, 7, 2, 6, 6, 8]; var index = 0; function check() { if (index == decisions.length) throw 'HALT'; return decisions[index++] }"); + Block *b1 = new Block("print(1); state = check();"); + Block *b2 = new Block("print(2); state = check();"); + Block *b3 = new Block("print(3); state = check();"); + Block *b4 = new Block("print(4); state = check();"); + Block *b5 = new Block("print(5); state = check();"); + Block *b6 = new Block("print(6); state = check();"); + Block *b7 = new Block("print(7); state = check();"); + Block *b8 = new Block("print(8); state = check();"); + b0->AddBranchTo(b5, NULL); + b1->AddBranchTo(b3, NULL); + b2->AddBranchTo(b1, NULL); + b3->AddBranchTo(b8, "state == 8"); + b3->AddBranchTo(b1, NULL); + b4->AddBranchTo(b3, "state == 3"); + b4->AddBranchTo(b1, NULL); + b5->AddBranchTo(b6, NULL); + b6->AddBranchTo(b7, "state == 7"); + b6->AddBranchTo(b1, NULL); + b7->AddBranchTo(b2, NULL); + b8->AddBranchTo(b4, "state == 4"); + b8->AddBranchTo(b2, NULL); + + Relooper r; + r.AddBlock(b0); + r.AddBlock(b1); + r.AddBlock(b2); + r.AddBlock(b3); + r.AddBlock(b4); + r.AddBlock(b5); + r.AddBlock(b6); + r.AddBlock(b7); + r.AddBlock(b8); + + r.Calculate(b0); + printf("\n\n"); + r.Render(); + + puts(buffer); + + return 1; +} diff --git a/src/relooper/test_fuzz1.txt b/src/relooper/test_fuzz1.txt new file mode 100644 index 0000000000000..63bbee0c01563 --- /dev/null +++ b/src/relooper/test_fuzz1.txt @@ -0,0 +1,44 @@ + + +print('entry'); var label; var state; var decisions = [4, 1, 7, 2, 6, 6, 8]; var index = 0; function check() { if (index == decisions.length) throw 'HALT'; return decisions[index++] } +print(5); state = check(); +print(6); state = check(); +do { + if (state == 7) { + print(7); state = check(); + label = 3; + break; + } else { + label = 2; + } +} while(0); +L5: while(1) { + if (label == 2) { + label = 0; + print(1); state = check(); + while(1) { + print(3); state = check(); + if (!(state == 8)) { + label = 2; + continue L5; + } + print(8); state = check(); + if (!(state == 4)) { + label = 3; + continue L5; + } + print(4); state = check(); + if (!(state == 3)) { + label = 2; + continue L5; + } + } + } + else if (label == 3) { + label = 0; + print(2); state = check(); + label = 2; + continue; + } +} + diff --git a/src/relooper/test_fuzz2.cpp b/src/relooper/test_fuzz2.cpp new file mode 100644 index 0000000000000..003753406cada --- /dev/null +++ b/src/relooper/test_fuzz2.cpp @@ -0,0 +1,34 @@ + + +#include +#include "Relooper.h" + +int main() { + #define SIZE (10*1024*1024) + char *buffer = (char*)malloc(SIZE); + Relooper::SetOutputBuffer(buffer, SIZE); + + Block *b0 = new Block("print('entry'); var label; var state; var decisions = [4, 1, 4, 3, 4, 1, 2, 5, 1, 3, 5, 5, 1, 5, 2, 4, 4, 3]; var index = 0; function check() { if (index == decisions.length) throw 'HALT'; return decisions[index++] }"); + Block *b1 = new Block("print(1); state = check();"); + Block *b2 = new Block("print(2); state = check();"); + Block *b3 = new Block("print(3); state = check();"); + b0->AddBranchTo(b1, "state == 1"); + b0->AddBranchTo(b3, NULL); + b1->AddBranchTo(b1, NULL); + b2->AddBranchTo(b3, NULL); + b3->AddBranchTo(b2, NULL); + + Relooper r; + r.AddBlock(b0); + r.AddBlock(b1); + r.AddBlock(b2); + r.AddBlock(b3); + + r.Calculate(b0); + printf("\n\n"); + r.Render(); + + puts(buffer); + + return 1; +} diff --git a/src/relooper/test_fuzz2.txt b/src/relooper/test_fuzz2.txt new file mode 100644 index 0000000000000..c48c6b6ca91d9 --- /dev/null +++ b/src/relooper/test_fuzz2.txt @@ -0,0 +1,14 @@ + + +print('entry'); var label; var state; var decisions = [4, 1, 4, 3, 4, 1, 2, 5, 1, 3, 5, 5, 1, 5, 2, 4, 4, 3]; var index = 0; function check() { if (index == decisions.length) throw 'HALT'; return decisions[index++] } +if (state == 1) { + while(1) { + print(1); state = check(); + } +} else { + while(1) { + print(3); state = check(); + print(2); state = check(); + } +} + diff --git a/src/relooper/test_fuzz3.cpp b/src/relooper/test_fuzz3.cpp new file mode 100644 index 0000000000000..3f39f5da23793 --- /dev/null +++ b/src/relooper/test_fuzz3.cpp @@ -0,0 +1,36 @@ + + +#include +#include "Relooper.h" + +int main() { + #define SIZE (10*1024*1024) + char *buffer = (char*)malloc(SIZE); + Relooper::SetOutputBuffer(buffer, SIZE); + + Block *b0 = new Block("print('entry'); var label; var state; var decisions = [3, 3, 4, 1, 2, 1, 2, 4, 4, 4, 2, 3, 3, 1, 2]; var index = 0; function check() { if (index == decisions.length) throw 'HALT'; return decisions[index++] }"); + Block *b1 = new Block("print(1); state = check();"); + Block *b2 = new Block("print(2); state = check();"); + Block *b3 = new Block("print(3); state = check();"); + Block *b4 = new Block("print(4); state = check();"); + b0->AddBranchTo(b1, NULL); + b1->AddBranchTo(b3, NULL); + b2->AddBranchTo(b1, NULL); + b3->AddBranchTo(b4, NULL); + b4->AddBranchTo(b4, NULL); + + Relooper r; + r.AddBlock(b0); + r.AddBlock(b1); + r.AddBlock(b2); + r.AddBlock(b3); + r.AddBlock(b4); + + r.Calculate(b0); + printf("\n\n"); + r.Render(); + + puts(buffer); + + return 1; +} diff --git a/src/relooper/test_fuzz3.txt b/src/relooper/test_fuzz3.txt new file mode 100644 index 0000000000000..aeeccf8731503 --- /dev/null +++ b/src/relooper/test_fuzz3.txt @@ -0,0 +1,9 @@ + + +print('entry'); var label; var state; var decisions = [3, 3, 4, 1, 2, 1, 2, 4, 4, 4, 2, 3, 3, 1, 2]; var index = 0; function check() { if (index == decisions.length) throw 'HALT'; return decisions[index++] } +print(1); state = check(); +print(3); state = check(); +while(1) { + print(4); state = check(); +} + diff --git a/src/relooper/test_fuzz4.cpp b/src/relooper/test_fuzz4.cpp new file mode 100644 index 0000000000000..8f9693869c4fc --- /dev/null +++ b/src/relooper/test_fuzz4.cpp @@ -0,0 +1,38 @@ + + +#include +#include "Relooper.h" + +int main() { + #define SIZE (10*1024*1024) + char *buffer = (char*)malloc(SIZE); + Relooper::SetOutputBuffer(buffer, SIZE); + + Block *b0 = new Block("print('entry'); var label; var state; var decisions = [2, 2, 1, 3, 2, 2, 1, 3, 2, 3, 3, 1, 3, 2, 1]; var index = 0; function check() { if (index == decisions.length) throw 'HALT'; return decisions[index++] }"); + Block *b1 = new Block("print(1); state = check();"); + Block *b2 = new Block("print(2); state = check();"); + Block *b3 = new Block("print(3); state = check();"); + Block *b4 = new Block("print(4); state = check();"); + b0->AddBranchTo(b2, "state == 2"); + b0->AddBranchTo(b4, NULL); + b1->AddBranchTo(b1, NULL); + b2->AddBranchTo(b2, NULL); + b3->AddBranchTo(b1, NULL); + b4->AddBranchTo(b4, "state == 4"); + b4->AddBranchTo(b3, NULL); + + Relooper r; + r.AddBlock(b0); + r.AddBlock(b1); + r.AddBlock(b2); + r.AddBlock(b3); + r.AddBlock(b4); + + r.Calculate(b0); + printf("\n\n"); + r.Render(); + + puts(buffer); + + return 1; +} diff --git a/src/relooper/test_fuzz4.txt b/src/relooper/test_fuzz4.txt new file mode 100644 index 0000000000000..5bb219f4af6be --- /dev/null +++ b/src/relooper/test_fuzz4.txt @@ -0,0 +1,20 @@ + + +print('entry'); var label; var state; var decisions = [2, 2, 1, 3, 2, 2, 1, 3, 2, 3, 3, 1, 3, 2, 1]; var index = 0; function check() { if (index == decisions.length) throw 'HALT'; return decisions[index++] } +if (state == 2) { + while(1) { + print(2); state = check(); + } +} else { + while(1) { + print(4); state = check(); + if (!(state == 4)) { + break; + } + } + print(3); state = check(); + while(1) { + print(1); state = check(); + } +} + diff --git a/src/relooper/test_fuzz5.cpp b/src/relooper/test_fuzz5.cpp new file mode 100644 index 0000000000000..f48c31eeaa070 --- /dev/null +++ b/src/relooper/test_fuzz5.cpp @@ -0,0 +1,57 @@ + + +#include +#include "Relooper.h" + +int main() { + #define SIZE (10*1024*1024) + char *buffer = (char*)malloc(SIZE); + Relooper::SetOutputBuffer(buffer, SIZE); + + Block *b0 = new Block("print('entry'); var label; var state; var decisions = [133, 98, 134, 143, 162, 187, 130, 87, 91, 49, 102, 47, 9, 132, 179, 176, 157, 25, 64, 161, 57, 107, 16, 167, 185, 45, 191, 180, 23, 131]; var index = 0; function check() { if (index == decisions.length) throw 'HALT'; return decisions[index++] }"); + Block *b1 = new Block("print(1); state = check();"); + Block *b2 = new Block("print(2); state = check();"); + Block *b3 = new Block("print(3); state = check();"); + Block *b4 = new Block("print(4); state = check();"); + Block *b5 = new Block("print(5); state = check();"); + Block *b6 = new Block("print(6); state = check();"); + Block *b7 = new Block("print(7); state = check();"); + Block *b8 = new Block("print(8); state = check();"); + Block *b9 = new Block("print(9); state = check();"); + b0->AddBranchTo(b7, NULL); + b1->AddBranchTo(b4, "state % 2 == 0"); + b1->AddBranchTo(b6, NULL); + b2->AddBranchTo(b1, NULL); + b3->AddBranchTo(b3, NULL); + b4->AddBranchTo(b2, NULL); + b5->AddBranchTo(b1, NULL); + b6->AddBranchTo(b7, "state % 2 == 0"); + b6->AddBranchTo(b6, NULL); + b7->AddBranchTo(b8, "state % 3 == 0"); + b7->AddBranchTo(b2, "state % 3 == 1"); + b7->AddBranchTo(b3, NULL); + b8->AddBranchTo(b4, "state % 2 == 0"); + b8->AddBranchTo(b6, NULL); + b9->AddBranchTo(b7, "state % 2 == 0"); + b9->AddBranchTo(b8, NULL); + + Relooper r; + r.AddBlock(b0); + r.AddBlock(b1); + r.AddBlock(b2); + r.AddBlock(b3); + r.AddBlock(b4); + r.AddBlock(b5); + r.AddBlock(b6); + r.AddBlock(b7); + r.AddBlock(b8); + r.AddBlock(b9); + + r.Calculate(b0); + printf("\n\n"); + r.Render(); + + puts(buffer); + + return 1; +} diff --git a/src/relooper/test_fuzz5.txt b/src/relooper/test_fuzz5.txt new file mode 100644 index 0000000000000..9548205cad66c --- /dev/null +++ b/src/relooper/test_fuzz5.txt @@ -0,0 +1,56 @@ + + +print('entry'); var label; var state; var decisions = [133, 98, 134, 143, 162, 187, 130, 87, 91, 49, 102, 47, 9, 132, 179, 176, 157, 25, 64, 161, 57, 107, 16, 167, 185, 45, 191, 180, 23, 131]; var index = 0; function check() { if (index == decisions.length) throw 'HALT'; return decisions[index++] } +L1: while(1) { + print(7); state = check(); + do { + if (state % 3 == 1) { + label = 3; + } else if (state % 3 == 0) { + print(8); state = check(); + if (state % 2 == 0) { + label = 5; + break; + } else { + label = 7; + break; + } + } else { + break L1; + } + } while(0); + while(1) { + if (label == 3) { + label = 0; + print(2); state = check(); + print(1); state = check(); + if (state % 2 == 0) { + label = 5; + continue; + } else { + label = 7; + continue; + } + } + else if (label == 5) { + label = 0; + print(4); state = check(); + label = 3; + continue; + } + else if (label == 7) { + label = 0; + print(6); state = check(); + if (state % 2 == 0) { + continue L1; + } else { + label = 7; + continue; + } + } + } +} +while(1) { + print(3); state = check(); +} + diff --git a/src/relooper/test_fuzz6.cpp b/src/relooper/test_fuzz6.cpp new file mode 100644 index 0000000000000..76a016d685b1d --- /dev/null +++ b/src/relooper/test_fuzz6.cpp @@ -0,0 +1,322 @@ + + +#include +#include "Relooper.h" + +int main() { + #define SIZE (10*1024*1024) + char *buffer = (char*)malloc(SIZE); + Relooper::SetOutputBuffer(buffer, SIZE); + + Block *b0 = new Block("print('entry'); var label; var state; var decisions = [759, 1223, 618, 1805, 277, 512, 204, 1545, 606, 734, 585, 447, 1670, 1031, 665, 1728, 353, 634, 1033, 13, 658, 589, 474, 854, 405, 1111, 1640, 697, 1156, 1357, 317, 618, 990, 1401, 405, 564, 497, 829, 653, 1194, 25, 322, 1178, 198, 1565, 1419, 1608, 486, 368, 606, 813, 22, 148, 141, 261, 375, 472, 964, 1106, 694, 205, 771, 44, 675, 545, 1027, 1528, 240, 1289, 564, 792, 744, 366, 668, 823, 210, 428, 1009, 1662, 1317, 1183, 681, 14, 1334, 712, 506, 224, 695, 401, 1035, 384, 486, 1519, 122, 1186, 1487, 1819, 1702, 463, 1706, 660, 1642, 847, 991, 976, 940, 867, 46, 23, 1449, 56, 1711, 634, 404, 1558, 168, 710, 1581, 1302, 870, 997, 1295, 1739, 769, 1005, 291, 1638, 1771, 842, 659, 1695, 713, 935, 802, 1173, 1572, 850, 607, 996, 55, 1576, 321, 1815, 662, 1044, 1612, 1680, 1050, 844, 553, 278, 1447, 1662, 1094, 1797, 774, 1013, 1204, 907, 340, 1172, 1460, 869, 1264, 111, 1176, 484, 845, 258, 417, 1246, 1017, 745, 189, 333, 1658, 1395, 1764, 1786, 165, 404, 847, 1429, 1574, 403, 718, 1118, 1756, 94, 56, 1498, 1696, 1355, 840, 50, 82, 371, 1087, 875, 1337, 267, 958, 1209, 1167, 1025, 1684, 184, 962, 1496, 201, 127, 372, 1, 1005, 402, 1387, 213, 1143, 1271, 167, 10, 12, 1060, 1390, 1366, 893, 747, 1005, 481, 876, 227, 514, 589, 250, 273, 1188, 1052, 719, 219, 1006, 38, 120, 1454, 489, 672, 149, 534, 1081, 1721, 586, 330, 25, 356, 1743, 1607, 336, 981, 419, 1036, 1293, 1026, 1300, 1453, 792, 22, 45, 420, 409, 1027, 1437, 1421, 795, 136, 1276, 1610, 1593]; var index = 0; function check() { if (index == decisions.length) throw 'HALT'; return decisions[index++] }"); + Block *b1 = new Block("print(1); state = check();// ..........................................................................."); + Block *b2 = new Block("print(2); state = check();// ........."); + Block *b3 = new Block("print(3); state = check();// .................................."); + Block *b4 = new Block("print(4); state = check();// ..........................................................................................................................."); + Block *b5 = new Block("print(5); state = check();// .........................................................................................................................................."); + Block *b6 = new Block("print(6); state = check();// ........."); + Block *b7 = new Block("print(7); state = check();// ............................................................................................................................................................................................."); + Block *b8 = new Block("print(8); state = check();// ...................................................................................................................................................................................................................................................."); + Block *b9 = new Block("print(9); state = check();// ..................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................."); + Block *b10 = new Block("print(10); state = check();// ..................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................."); + Block *b11 = new Block("print(11); state = check();// ........................................................"); + Block *b12 = new Block("print(12); state = check();// ................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................"); + Block *b13 = new Block("print(13); state = check();// ..................."); + Block *b14 = new Block("print(14); state = check();// ............................."); + Block *b15 = new Block("print(15); state = check();// .................................................."); + Block *b16 = new Block("print(16); state = check();// ................................................................................................................................................................................................................................................................................................................................................................"); + Block *b17 = new Block("print(17); state = check();// ................................................................"); + Block *b18 = new Block("print(18); state = check();// .............................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................."); + Block *b19 = new Block("print(19); state = check();// ......................................................................................................................................................................................................................"); + Block *b20 = new Block("print(20); state = check();// .................................................................................................................................................................."); + Block *b21 = new Block("print(21); state = check();// ..........................."); + Block *b22 = new Block("print(22); state = check();// ........................................................................................................."); + Block *b23 = new Block("print(23); state = check();// ................................................................................................................................................................................................................."); + Block *b24 = new Block("print(24); state = check();// ..........................."); + Block *b25 = new Block("print(25); state = check();// ......................................................................................................................................................"); + Block *b26 = new Block("print(26); state = check();// ........................................................................................................................................................................................................................................................................."); + Block *b27 = new Block("print(27); state = check();// ............................................................................................................................................................................."); + Block *b28 = new Block("print(28); state = check();// .............................................................................................................."); + Block *b29 = new Block("print(29); state = check();// ..............."); + Block *b30 = new Block("print(30); state = check();// ................................................................................................................................................................................................................."); + Block *b31 = new Block("print(31); state = check();// .........................................................................................................................................................................................................."); + Block *b32 = new Block("print(32); state = check();// ......................................................................................................"); + Block *b33 = new Block("print(33); state = check();// ...."); + Block *b34 = new Block("print(34); state = check();// .........................................................................................................................................."); + Block *b35 = new Block("print(35); state = check();// ................................."); + Block *b36 = new Block("print(36); state = check();// ........................."); + Block *b37 = new Block("print(37); state = check();// ................................................................................................................................"); + Block *b38 = new Block("print(38); state = check();// ............................................................................................................................................................................................................................................................................................................................................"); + Block *b39 = new Block("print(39); state = check();// ................"); + Block *b40 = new Block("print(40); state = check();// ................................................................................................................................................"); + Block *b41 = new Block("print(41); state = check();// ..................................................................................................................................."); + Block *b42 = new Block("print(42); state = check();// ....................................................."); + Block *b43 = new Block("print(43); state = check();// ........."); + Block *b44 = new Block("print(44); state = check();// ....................................................................................................................................................."); + Block *b45 = new Block("print(45); state = check();// ............................"); + Block *b46 = new Block("print(46); state = check();// ............................................................................."); + Block *b47 = new Block("print(47); state = check();// ...................................................................................................................................."); + Block *b48 = new Block("print(48); state = check();// ............"); + Block *b49 = new Block("print(49); state = check();// ............................................................................................................................................................................................................................................................................................"); + Block *b50 = new Block("print(50); state = check();// ........................................"); + Block *b51 = new Block("print(51); state = check();// ............................................................................................."); + Block *b52 = new Block("print(52); state = check();// .............................................................................."); + Block *b53 = new Block("print(53); state = check();// .............................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................."); + Block *b54 = new Block("print(54); state = check();// ....................................."); + Block *b55 = new Block("print(55); state = check();// ..........................................................................................................................................................................................................."); + Block *b56 = new Block("print(56); state = check();// ...................................................................................................................................................................................................................."); + Block *b57 = new Block("print(57); state = check();// ..........................................................................................................................................................................................................................................................................................................................."); + Block *b58 = new Block("print(58); state = check();// ......................................................................................"); + Block *b59 = new Block("print(59); state = check();// ..................................."); + Block *b60 = new Block("print(60); state = check();// ......................................................................................................................................................................................................................................"); + Block *b61 = new Block("print(61); state = check();// ........................................................................................................................................................."); + Block *b62 = new Block("print(62); state = check();// ......................................................................................."); + Block *b63 = new Block("print(63); state = check();// ....................................................................................................................................................................."); + Block *b64 = new Block("print(64); state = check();// ......................................................................................................................................................................................................................................................................."); + Block *b65 = new Block("print(65); state = check();// ........................................................."); + Block *b66 = new Block("print(66); state = check();// ..............................................................................................................."); + Block *b67 = new Block("print(67); state = check();// ....................................................................................................................................................................................................................."); + Block *b68 = new Block("print(68); state = check();// ......................................................................................................................................................................................................................................................................................................................"); + Block *b69 = new Block("print(69); state = check();// ......................................................................................................................................................"); + Block *b70 = new Block("print(70); state = check();// .........................................................................................................................."); + Block *b71 = new Block("print(71); state = check();// ..........................................................................................................................................................................................................."); + Block *b72 = new Block("print(72); state = check();// .........................................................................................................."); + Block *b73 = new Block("print(73); state = check();// ."); + Block *b74 = new Block("print(74); state = check();// .............................................."); + Block *b75 = new Block("print(75); state = check();// ............................................."); + Block *b76 = new Block("print(76); state = check();// .............................................................................................................................................................................................................................................................................................................................................................................................................................."); + Block *b77 = new Block("print(77); state = check();// ..........................................................................................................................................................................................................................................................................................."); + Block *b78 = new Block("print(78); state = check();// .........................................................................................."); + Block *b79 = new Block("print(79); state = check();// ..................................................................................................................................................................................................................................................."); + Block *b80 = new Block("print(80); state = check();// ...................................."); + Block *b81 = new Block("print(81); state = check();// ................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................"); + Block *b82 = new Block("print(82); state = check();// ...................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................."); + Block *b83 = new Block("print(83); state = check();// ........................................................................................"); + Block *b84 = new Block("print(84); state = check();// ..................."); + Block *b85 = new Block("print(85); state = check();// ........................................................................................................................................................................................................................................................................................................................................................."); + Block *b86 = new Block("print(86); state = check();// ................................................................................................................................................................................................................................................."); + Block *b87 = new Block("print(87); state = check();// ......"); + Block *b88 = new Block("print(88); state = check();// ...................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................."); + Block *b89 = new Block("print(89); state = check();// ......................................................................................................................................................................................................................................................................................................................................................"); + Block *b90 = new Block("print(90); state = check();// ..........................................................................................................................................................................................................................."); + Block *b91 = new Block("print(91); state = check();// .............................................."); + b0->AddBranchTo(b30, NULL); + b1->AddBranchTo(b66, NULL); + b2->AddBranchTo(b51, NULL); + b3->AddBranchTo(b57, NULL); + b4->AddBranchTo(b31, NULL); + b5->AddBranchTo(b21, NULL); + b6->AddBranchTo(b88, NULL); + b7->AddBranchTo(b75, "state % 2 == 0"); + b7->AddBranchTo(b89, NULL); + b8->AddBranchTo(b47, "state % 2 == 0"); + b8->AddBranchTo(b19, NULL); + b9->AddBranchTo(b66, NULL); + b10->AddBranchTo(b52, NULL); + b11->AddBranchTo(b40, NULL); + b12->AddBranchTo(b87, NULL); + b13->AddBranchTo(b72, "state % 3 == 0"); + b13->AddBranchTo(b6, "state % 3 == 1"); + b13->AddBranchTo(b55, NULL); + b14->AddBranchTo(b2, "state % 2 == 0"); + b14->AddBranchTo(b52, NULL); + b15->AddBranchTo(b11, NULL); + b16->AddBranchTo(b57, NULL); + b17->AddBranchTo(b1, "state % 2 == 0"); + b17->AddBranchTo(b24, NULL); + b18->AddBranchTo(b67, NULL); + b19->AddBranchTo(b56, NULL); + b20->AddBranchTo(b34, NULL); + b21->AddBranchTo(b25, NULL); + b22->AddBranchTo(b72, NULL); + b23->AddBranchTo(b64, NULL); + b24->AddBranchTo(b36, NULL); + b25->AddBranchTo(b88, NULL); + b26->AddBranchTo(b56, NULL); + b27->AddBranchTo(b3, NULL); + b28->AddBranchTo(b75, NULL); + b29->AddBranchTo(b8, NULL); + b30->AddBranchTo(b58, "state % 3 == 0"); + b30->AddBranchTo(b66, "state % 3 == 1"); + b30->AddBranchTo(b6, NULL); + b31->AddBranchTo(b60, NULL); + b32->AddBranchTo(b83, NULL); + b33->AddBranchTo(b60, NULL); + b34->AddBranchTo(b73, NULL); + b35->AddBranchTo(b7, NULL); + b36->AddBranchTo(b60, "state % 2 == 0"); + b36->AddBranchTo(b16, NULL); + b37->AddBranchTo(b82, NULL); + b38->AddBranchTo(b45, NULL); + b39->AddBranchTo(b72, "state % 3 == 0"); + b39->AddBranchTo(b73, "state % 3 == 1"); + b39->AddBranchTo(b31, NULL); + b40->AddBranchTo(b89, NULL); + b41->AddBranchTo(b64, "state % 2 == 0"); + b41->AddBranchTo(b90, NULL); + b42->AddBranchTo(b12, NULL); + b43->AddBranchTo(b32, NULL); + b44->AddBranchTo(b28, NULL); + b45->AddBranchTo(b63, "state % 2 == 0"); + b45->AddBranchTo(b47, NULL); + b46->AddBranchTo(b70, "state % 2 == 0"); + b46->AddBranchTo(b42, NULL); + b47->AddBranchTo(b28, NULL); + b48->AddBranchTo(b20, "state % 2 == 0"); + b48->AddBranchTo(b91, NULL); + b49->AddBranchTo(b6, NULL); + b50->AddBranchTo(b29, NULL); + b51->AddBranchTo(b36, NULL); + b52->AddBranchTo(b61, "state % 2 == 0"); + b52->AddBranchTo(b2, NULL); + b53->AddBranchTo(b75, "state % 2 == 0"); + b53->AddBranchTo(b46, NULL); + b54->AddBranchTo(b30, NULL); + b55->AddBranchTo(b59, NULL); + b56->AddBranchTo(b34, NULL); + b57->AddBranchTo(b39, NULL); + b58->AddBranchTo(b30, NULL); + b59->AddBranchTo(b47, NULL); + b60->AddBranchTo(b10, NULL); + b61->AddBranchTo(b88, NULL); + b62->AddBranchTo(b36, NULL); + b63->AddBranchTo(b54, NULL); + b64->AddBranchTo(b79, NULL); + b65->AddBranchTo(b65, NULL); + b66->AddBranchTo(b6, NULL); + b67->AddBranchTo(b78, NULL); + b68->AddBranchTo(b51, NULL); + b69->AddBranchTo(b32, NULL); + b70->AddBranchTo(b47, NULL); + b71->AddBranchTo(b38, NULL); + b72->AddBranchTo(b91, "state % 2 == 0"); + b72->AddBranchTo(b80, NULL); + b73->AddBranchTo(b62, "state % 3 == 0"); + b73->AddBranchTo(b31, "state % 3 == 1"); + b73->AddBranchTo(b43, NULL); + b74->AddBranchTo(b77, NULL); + b75->AddBranchTo(b7, NULL); + b76->AddBranchTo(b22, NULL); + b77->AddBranchTo(b76, NULL); + b78->AddBranchTo(b14, "state % 2 == 0"); + b78->AddBranchTo(b62, NULL); + b79->AddBranchTo(b81, NULL); + b80->AddBranchTo(b51, "state % 2 == 0"); + b80->AddBranchTo(b50, NULL); + b81->AddBranchTo(b40, NULL); + b82->AddBranchTo(b60, "state % 2 == 0"); + b82->AddBranchTo(b43, NULL); + b83->AddBranchTo(b77, NULL); + b84->AddBranchTo(b60, "state % 2 == 0"); + b84->AddBranchTo(b77, NULL); + b85->AddBranchTo(b42, NULL); + b86->AddBranchTo(b85, "state % 2 == 0"); + b86->AddBranchTo(b88, NULL); + b87->AddBranchTo(b88, NULL); + b88->AddBranchTo(b70, NULL); + b89->AddBranchTo(b68, NULL); + b90->AddBranchTo(b33, NULL); + b91->AddBranchTo(b33, NULL); + + Relooper r; + r.AddBlock(b0); + r.AddBlock(b1); + r.AddBlock(b2); + r.AddBlock(b3); + r.AddBlock(b4); + r.AddBlock(b5); + r.AddBlock(b6); + r.AddBlock(b7); + r.AddBlock(b8); + r.AddBlock(b9); + r.AddBlock(b10); + r.AddBlock(b11); + r.AddBlock(b12); + r.AddBlock(b13); + r.AddBlock(b14); + r.AddBlock(b15); + r.AddBlock(b16); + r.AddBlock(b17); + r.AddBlock(b18); + r.AddBlock(b19); + r.AddBlock(b20); + r.AddBlock(b21); + r.AddBlock(b22); + r.AddBlock(b23); + r.AddBlock(b24); + r.AddBlock(b25); + r.AddBlock(b26); + r.AddBlock(b27); + r.AddBlock(b28); + r.AddBlock(b29); + r.AddBlock(b30); + r.AddBlock(b31); + r.AddBlock(b32); + r.AddBlock(b33); + r.AddBlock(b34); + r.AddBlock(b35); + r.AddBlock(b36); + r.AddBlock(b37); + r.AddBlock(b38); + r.AddBlock(b39); + r.AddBlock(b40); + r.AddBlock(b41); + r.AddBlock(b42); + r.AddBlock(b43); + r.AddBlock(b44); + r.AddBlock(b45); + r.AddBlock(b46); + r.AddBlock(b47); + r.AddBlock(b48); + r.AddBlock(b49); + r.AddBlock(b50); + r.AddBlock(b51); + r.AddBlock(b52); + r.AddBlock(b53); + r.AddBlock(b54); + r.AddBlock(b55); + r.AddBlock(b56); + r.AddBlock(b57); + r.AddBlock(b58); + r.AddBlock(b59); + r.AddBlock(b60); + r.AddBlock(b61); + r.AddBlock(b62); + r.AddBlock(b63); + r.AddBlock(b64); + r.AddBlock(b65); + r.AddBlock(b66); + r.AddBlock(b67); + r.AddBlock(b68); + r.AddBlock(b69); + r.AddBlock(b70); + r.AddBlock(b71); + r.AddBlock(b72); + r.AddBlock(b73); + r.AddBlock(b74); + r.AddBlock(b75); + r.AddBlock(b76); + r.AddBlock(b77); + r.AddBlock(b78); + r.AddBlock(b79); + r.AddBlock(b80); + r.AddBlock(b81); + r.AddBlock(b82); + r.AddBlock(b83); + r.AddBlock(b84); + r.AddBlock(b85); + r.AddBlock(b86); + r.AddBlock(b87); + r.AddBlock(b88); + r.AddBlock(b89); + r.AddBlock(b90); + r.AddBlock(b91); + + r.Calculate(b0); + printf("\n\n"); + r.Render(); + + puts(buffer); + + return 1; +} diff --git a/src/relooper/test_fuzz6.txt b/src/relooper/test_fuzz6.txt new file mode 100644 index 0000000000000..af188ab15c652 --- /dev/null +++ b/src/relooper/test_fuzz6.txt @@ -0,0 +1,116 @@ + + +print('entry'); var label; var state; var decisions = [759, 1223, 618, 1805, 277, 512, 204, 1545, 606, 734, 585, 447, 1670, 1031, 665, 1728, 353, 634, 1033, 13, 658, 589, 474, 854, 405, 1111, 1640, 697, 1156, 1357, 317, 618, 990, 1401, 405, 564, 497, 829, 653, 1194, 25, 322, 1178, 198, 1565, 1419, 1608, 486, 368, 606, 813, 22, 148, 141, 261, 375, 472, 964, 1106, 694, 205, 771, 44, 675, 545, 1027, 1528, 240, 1289, 564, 792, 744, 366, 668, 823, 210, 428, 1009, 1662, 1317, 1183, 681, 14, 1334, 712, 506, 224, 695, 401, 1035, 384, 486, 1519, 122, 1186, 1487, 1819, 1702, 463, 1706, 660, 1642, 847, 991, 976, 940, 867, 46, 23, 1449, 56, 1711, 634, 404, 1558, 168, 710, 1581, 1302, 870, 997, 1295, 1739, 769, 1005, 291, 1638, 1771, 842, 659, 1695, 713, 935, 802, 1173, 1572, 850, 607, 996, 55, 1576, 321, 1815, 662, 1044, 1612, 1680, 1050, 844, 553, 278, 1447, 1662, 1094, 1797, 774, 1013, 1204, 907, 340, 1172, 1460, 869, 1264, 111, 1176, 484, 845, 258, 417, 1246, 1017, 745, 189, 333, 1658, 1395, 1764, 1786, 165, 404, 847, 1429, 1574, 403, 718, 1118, 1756, 94, 56, 1498, 1696, 1355, 840, 50, 82, 371, 1087, 875, 1337, 267, 958, 1209, 1167, 1025, 1684, 184, 962, 1496, 201, 127, 372, 1, 1005, 402, 1387, 213, 1143, 1271, 167, 10, 12, 1060, 1390, 1366, 893, 747, 1005, 481, 876, 227, 514, 589, 250, 273, 1188, 1052, 719, 219, 1006, 38, 120, 1454, 489, 672, 149, 534, 1081, 1721, 586, 330, 25, 356, 1743, 1607, 336, 981, 419, 1036, 1293, 1026, 1300, 1453, 792, 22, 45, 420, 409, 1027, 1437, 1421, 795, 136, 1276, 1610, 1593]; var index = 0; function check() { if (index == decisions.length) throw 'HALT'; return decisions[index++] } +while(1) { + print(30); state = check();// ................................................................................................................................................................................................................. + if (state % 3 == 1) { + label = 67; + break; + } else if (!(state % 3 == 0)) { + break; + } + print(58); state = check();// ...................................................................................... +} +if (label == 67) { + print(66); state = check();// ............................................................................................................... +} +print(6); state = check();// ......... +while(1) { + print(88); state = check();// .................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................... + print(70); state = check();// .......................................................................................................................... + L10: while(1) { + print(47); state = check();// .................................................................................................................................... + print(28); state = check();// .............................................................................................................. + while(1) { + print(75); state = check();// ............................................. + print(7); state = check();// ............................................................................................................................................................................................. + if (!(state % 2 == 0)) { + break; + } + } + print(89); state = check();// ...................................................................................................................................................................................................................................................................................................................................................... + print(68); state = check();// ...................................................................................................................................................................................................................................................................................................................... + L18: while(1) { + print(51); state = check();// ............................................................................................. + L20: while(1) { + print(36); state = check();// ......................... + if (state % 2 == 0) { + break; + } + print(16); state = check();// ................................................................................................................................................................................................................................................................................................................................................................ + print(57); state = check();// ........................................................................................................................................................................................................................................................................................................................... + print(39); state = check();// ................ + if (state % 3 == 0) { + label = 73; + } else if (state % 3 == 1) { + label = 74; + } else { + label = 32; + break; + } + while(1) { + if (label == 73) { + label = 0; + print(72); state = check();// .......................................................................................................... + if (state % 2 == 0) { + label = 92; + break L20; + } + print(80); state = check();// .................................... + if (state % 2 == 0) { + continue L18; + } + print(50); state = check();// ........................................ + print(29); state = check();// ............... + print(8); state = check();// .................................................................................................................................................................................................................................................... + if (state % 2 == 0) { + continue L10; + } + print(19); state = check();// ...................................................................................................................................................................................................................... + print(56); state = check();// .................................................................................................................................................................................................................... + print(34); state = check();// .......................................................................................................................................... + label = 74; + continue; + } + else if (label == 74) { + label = 0; + print(73); state = check();// . + if (state % 3 == 1) { + label = 32; + break L20; + } else if (state % 3 == 0) { + break; + } + print(43); state = check();// ......... + print(32); state = check();// ...................................................................................................... + print(83); state = check();// ........................................................................................ + print(77); state = check();// ........................................................................................................................................................................................................................................................................................... + print(76); state = check();// .............................................................................................................................................................................................................................................................................................................................................................................................................................. + print(22); state = check();// ......................................................................................................... + label = 73; + continue; + } + } + print(62); state = check();// ....................................................................................... + } + if (label == 32) { + label = 0; + print(31); state = check();// .......................................................................................................................................................................................................... + } + else if (label == 92) { + label = 0; + print(91); state = check();// .............................................. + print(33); state = check();// .... + } + print(60); state = check();// ...................................................................................................................................................................................................................................... + print(10); state = check();// ................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................... + print(52); state = check();// .............................................................................. + if (state % 2 == 0) { + break L10; + } + print(2); state = check();// ......... + } + } + print(61); state = check();// ......................................................................................................................................................... +} + diff --git a/src/relooper/test_inf.cpp b/src/relooper/test_inf.cpp new file mode 100644 index 0000000000000..66e712eda9e0f --- /dev/null +++ b/src/relooper/test_inf.cpp @@ -0,0 +1,813 @@ +#include "Relooper.h" +int main() { + void *block_map[10000]; + void *rl = rl_new_relooper(); + char buffer[100000]; + rl_set_output_buffer(buffer, sizeof(buffer)); + void *b0 = rl_new_block("code 0"); + block_map[0] = b0; + rl_relooper_add_block(rl, block_map[0]); + void *b1 = rl_new_block("code 1"); + block_map[1] = b1; + rl_relooper_add_block(rl, block_map[1]); + void *b2 = rl_new_block("code 2"); + block_map[2] = b2; + rl_relooper_add_block(rl, block_map[2]); + void *b3 = rl_new_block("code 3"); + block_map[3] = b3; + rl_relooper_add_block(rl, block_map[3]); + void *b4 = rl_new_block("code 4"); + block_map[4] = b4; + rl_relooper_add_block(rl, block_map[4]); + void *b5 = rl_new_block("code 5"); + block_map[5] = b5; + rl_relooper_add_block(rl, block_map[5]); + void *b6 = rl_new_block("code 6"); + block_map[6] = b6; + rl_relooper_add_block(rl, block_map[6]); + void *b7 = rl_new_block("code 7"); + block_map[7] = b7; + rl_relooper_add_block(rl, block_map[7]); + void *b8 = rl_new_block("code 8"); + block_map[8] = b8; + rl_relooper_add_block(rl, block_map[8]); + void *b9 = rl_new_block("code 9"); + block_map[9] = b9; + rl_relooper_add_block(rl, block_map[9]); + void *b10 = rl_new_block("code 10"); + block_map[10] = b10; + rl_relooper_add_block(rl, block_map[10]); + void *b11 = rl_new_block("code 11"); + block_map[11] = b11; + rl_relooper_add_block(rl, block_map[11]); + void *b12 = rl_new_block("code 12"); + block_map[12] = b12; + rl_relooper_add_block(rl, block_map[12]); + void *b13 = rl_new_block("code 13"); + block_map[13] = b13; + rl_relooper_add_block(rl, block_map[13]); + void *b14 = rl_new_block("code 14"); + block_map[14] = b14; + rl_relooper_add_block(rl, block_map[14]); + void *b15 = rl_new_block("code 15"); + block_map[15] = b15; + rl_relooper_add_block(rl, block_map[15]); + void *b16 = rl_new_block("code 16"); + block_map[16] = b16; + rl_relooper_add_block(rl, block_map[16]); + void *b17 = rl_new_block("code 17"); + block_map[17] = b17; + rl_relooper_add_block(rl, block_map[17]); + void *b18 = rl_new_block("code 18"); + block_map[18] = b18; + rl_relooper_add_block(rl, block_map[18]); + void *b19 = rl_new_block("code 19"); + block_map[19] = b19; + rl_relooper_add_block(rl, block_map[19]); + void *b20 = rl_new_block("code 20"); + block_map[20] = b20; + rl_relooper_add_block(rl, block_map[20]); + void *b21 = rl_new_block("code 21"); + block_map[21] = b21; + rl_relooper_add_block(rl, block_map[21]); + void *b22 = rl_new_block("code 22"); + block_map[22] = b22; + rl_relooper_add_block(rl, block_map[22]); + void *b23 = rl_new_block("code 23"); + block_map[23] = b23; + rl_relooper_add_block(rl, block_map[23]); + void *b24 = rl_new_block("code 24"); + block_map[24] = b24; + rl_relooper_add_block(rl, block_map[24]); + void *b25 = rl_new_block("code 25"); + block_map[25] = b25; + rl_relooper_add_block(rl, block_map[25]); + void *b26 = rl_new_block("code 26"); + block_map[26] = b26; + rl_relooper_add_block(rl, block_map[26]); + void *b27 = rl_new_block("code 27"); + block_map[27] = b27; + rl_relooper_add_block(rl, block_map[27]); + void *b28 = rl_new_block("code 28"); + block_map[28] = b28; + rl_relooper_add_block(rl, block_map[28]); + void *b29 = rl_new_block("code 29"); + block_map[29] = b29; + rl_relooper_add_block(rl, block_map[29]); + void *b30 = rl_new_block("code 30"); + block_map[30] = b30; + rl_relooper_add_block(rl, block_map[30]); + void *b31 = rl_new_block("code 31"); + block_map[31] = b31; + rl_relooper_add_block(rl, block_map[31]); + void *b32 = rl_new_block("code 32"); + block_map[32] = b32; + rl_relooper_add_block(rl, block_map[32]); + void *b33 = rl_new_block("code 33"); + block_map[33] = b33; + rl_relooper_add_block(rl, block_map[33]); + void *b34 = rl_new_block("code 34"); + block_map[34] = b34; + rl_relooper_add_block(rl, block_map[34]); + void *b35 = rl_new_block("code 35"); + block_map[35] = b35; + rl_relooper_add_block(rl, block_map[35]); + void *b36 = rl_new_block("code 36"); + block_map[36] = b36; + rl_relooper_add_block(rl, block_map[36]); + void *b37 = rl_new_block("code 37"); + block_map[37] = b37; + rl_relooper_add_block(rl, block_map[37]); + void *b38 = rl_new_block("code 38"); + block_map[38] = b38; + rl_relooper_add_block(rl, block_map[38]); + void *b39 = rl_new_block("code 39"); + block_map[39] = b39; + rl_relooper_add_block(rl, block_map[39]); + void *b40 = rl_new_block("code 40"); + block_map[40] = b40; + rl_relooper_add_block(rl, block_map[40]); + void *b41 = rl_new_block("code 41"); + block_map[41] = b41; + rl_relooper_add_block(rl, block_map[41]); + void *b42 = rl_new_block("code 42"); + block_map[42] = b42; + rl_relooper_add_block(rl, block_map[42]); + void *b43 = rl_new_block("code 43"); + block_map[43] = b43; + rl_relooper_add_block(rl, block_map[43]); + void *b44 = rl_new_block("code 44"); + block_map[44] = b44; + rl_relooper_add_block(rl, block_map[44]); + void *b45 = rl_new_block("code 45"); + block_map[45] = b45; + rl_relooper_add_block(rl, block_map[45]); + void *b46 = rl_new_block("code 46"); + block_map[46] = b46; + rl_relooper_add_block(rl, block_map[46]); + void *b47 = rl_new_block("code 47"); + block_map[47] = b47; + rl_relooper_add_block(rl, block_map[47]); + void *b48 = rl_new_block("code 48"); + block_map[48] = b48; + rl_relooper_add_block(rl, block_map[48]); + void *b49 = rl_new_block("code 49"); + block_map[49] = b49; + rl_relooper_add_block(rl, block_map[49]); + void *b50 = rl_new_block("code 50"); + block_map[50] = b50; + rl_relooper_add_block(rl, block_map[50]); + void *b51 = rl_new_block("code 51"); + block_map[51] = b51; + rl_relooper_add_block(rl, block_map[51]); + void *b52 = rl_new_block("code 52"); + block_map[52] = b52; + rl_relooper_add_block(rl, block_map[52]); + void *b53 = rl_new_block("code 53"); + block_map[53] = b53; + rl_relooper_add_block(rl, block_map[53]); + void *b54 = rl_new_block("code 54"); + block_map[54] = b54; + rl_relooper_add_block(rl, block_map[54]); + void *b55 = rl_new_block("code 55"); + block_map[55] = b55; + rl_relooper_add_block(rl, block_map[55]); + void *b56 = rl_new_block("code 56"); + block_map[56] = b56; + rl_relooper_add_block(rl, block_map[56]); + void *b57 = rl_new_block("code 57"); + block_map[57] = b57; + rl_relooper_add_block(rl, block_map[57]); + void *b58 = rl_new_block("code 58"); + block_map[58] = b58; + rl_relooper_add_block(rl, block_map[58]); + void *b59 = rl_new_block("code 59"); + block_map[59] = b59; + rl_relooper_add_block(rl, block_map[59]); + void *b60 = rl_new_block("code 60"); + block_map[60] = b60; + rl_relooper_add_block(rl, block_map[60]); + void *b61 = rl_new_block("code 61"); + block_map[61] = b61; + rl_relooper_add_block(rl, block_map[61]); + void *b62 = rl_new_block("code 62"); + block_map[62] = b62; + rl_relooper_add_block(rl, block_map[62]); + void *b63 = rl_new_block("code 63"); + block_map[63] = b63; + rl_relooper_add_block(rl, block_map[63]); + void *b64 = rl_new_block("code 64"); + block_map[64] = b64; + rl_relooper_add_block(rl, block_map[64]); + void *b65 = rl_new_block("code 65"); + block_map[65] = b65; + rl_relooper_add_block(rl, block_map[65]); + void *b66 = rl_new_block("code 66"); + block_map[66] = b66; + rl_relooper_add_block(rl, block_map[66]); + void *b67 = rl_new_block("code 67"); + block_map[67] = b67; + rl_relooper_add_block(rl, block_map[67]); + void *b68 = rl_new_block("code 68"); + block_map[68] = b68; + rl_relooper_add_block(rl, block_map[68]); + void *b69 = rl_new_block("code 69"); + block_map[69] = b69; + rl_relooper_add_block(rl, block_map[69]); + void *b70 = rl_new_block("code 70"); + block_map[70] = b70; + rl_relooper_add_block(rl, block_map[70]); + void *b71 = rl_new_block("code 71"); + block_map[71] = b71; + rl_relooper_add_block(rl, block_map[71]); + void *b72 = rl_new_block("code 72"); + block_map[72] = b72; + rl_relooper_add_block(rl, block_map[72]); + void *b73 = rl_new_block("code 73"); + block_map[73] = b73; + rl_relooper_add_block(rl, block_map[73]); + void *b74 = rl_new_block("code 74"); + block_map[74] = b74; + rl_relooper_add_block(rl, block_map[74]); + void *b75 = rl_new_block("code 75"); + block_map[75] = b75; + rl_relooper_add_block(rl, block_map[75]); + void *b76 = rl_new_block("code 76"); + block_map[76] = b76; + rl_relooper_add_block(rl, block_map[76]); + void *b77 = rl_new_block("code 77"); + block_map[77] = b77; + rl_relooper_add_block(rl, block_map[77]); + void *b78 = rl_new_block("code 78"); + block_map[78] = b78; + rl_relooper_add_block(rl, block_map[78]); + void *b79 = rl_new_block("code 79"); + block_map[79] = b79; + rl_relooper_add_block(rl, block_map[79]); + void *b80 = rl_new_block("code 80"); + block_map[80] = b80; + rl_relooper_add_block(rl, block_map[80]); + void *b81 = rl_new_block("code 81"); + block_map[81] = b81; + rl_relooper_add_block(rl, block_map[81]); + void *b82 = rl_new_block("code 82"); + block_map[82] = b82; + rl_relooper_add_block(rl, block_map[82]); + void *b83 = rl_new_block("code 83"); + block_map[83] = b83; + rl_relooper_add_block(rl, block_map[83]); + void *b84 = rl_new_block("code 84"); + block_map[84] = b84; + rl_relooper_add_block(rl, block_map[84]); + void *b85 = rl_new_block("code 85"); + block_map[85] = b85; + rl_relooper_add_block(rl, block_map[85]); + void *b86 = rl_new_block("code 86"); + block_map[86] = b86; + rl_relooper_add_block(rl, block_map[86]); + void *b87 = rl_new_block("code 87"); + block_map[87] = b87; + rl_relooper_add_block(rl, block_map[87]); + void *b88 = rl_new_block("code 88"); + block_map[88] = b88; + rl_relooper_add_block(rl, block_map[88]); + void *b89 = rl_new_block("code 89"); + block_map[89] = b89; + rl_relooper_add_block(rl, block_map[89]); + void *b90 = rl_new_block("code 90"); + block_map[90] = b90; + rl_relooper_add_block(rl, block_map[90]); + void *b91 = rl_new_block("code 91"); + block_map[91] = b91; + rl_relooper_add_block(rl, block_map[91]); + void *b92 = rl_new_block("code 92"); + block_map[92] = b92; + rl_relooper_add_block(rl, block_map[92]); + void *b93 = rl_new_block("code 93"); + block_map[93] = b93; + rl_relooper_add_block(rl, block_map[93]); + void *b94 = rl_new_block("code 94"); + block_map[94] = b94; + rl_relooper_add_block(rl, block_map[94]); + void *b95 = rl_new_block("code 95"); + block_map[95] = b95; + rl_relooper_add_block(rl, block_map[95]); + void *b96 = rl_new_block("code 96"); + block_map[96] = b96; + rl_relooper_add_block(rl, block_map[96]); + void *b97 = rl_new_block("code 97"); + block_map[97] = b97; + rl_relooper_add_block(rl, block_map[97]); + void *b98 = rl_new_block("code 98"); + block_map[98] = b98; + rl_relooper_add_block(rl, block_map[98]); + void *b99 = rl_new_block("code 99"); + block_map[99] = b99; + rl_relooper_add_block(rl, block_map[99]); + void *b100 = rl_new_block("code 100"); + block_map[100] = b100; + rl_relooper_add_block(rl, block_map[100]); + void *b101 = rl_new_block("code 101"); + block_map[101] = b101; + rl_relooper_add_block(rl, block_map[101]); + void *b102 = rl_new_block("code 102"); + block_map[102] = b102; + rl_relooper_add_block(rl, block_map[102]); + void *b103 = rl_new_block("code 103"); + block_map[103] = b103; + rl_relooper_add_block(rl, block_map[103]); + void *b104 = rl_new_block("code 104"); + block_map[104] = b104; + rl_relooper_add_block(rl, block_map[104]); + void *b105 = rl_new_block("code 105"); + block_map[105] = b105; + rl_relooper_add_block(rl, block_map[105]); + void *b106 = rl_new_block("code 106"); + block_map[106] = b106; + rl_relooper_add_block(rl, block_map[106]); + void *b107 = rl_new_block("code 107"); + block_map[107] = b107; + rl_relooper_add_block(rl, block_map[107]); + void *b108 = rl_new_block("code 108"); + block_map[108] = b108; + rl_relooper_add_block(rl, block_map[108]); + void *b109 = rl_new_block("code 109"); + block_map[109] = b109; + rl_relooper_add_block(rl, block_map[109]); + void *b110 = rl_new_block("code 110"); + block_map[110] = b110; + rl_relooper_add_block(rl, block_map[110]); + void *b111 = rl_new_block("code 111"); + block_map[111] = b111; + rl_relooper_add_block(rl, block_map[111]); + void *b112 = rl_new_block("code 112"); + block_map[112] = b112; + rl_relooper_add_block(rl, block_map[112]); + void *b113 = rl_new_block("code 113"); + block_map[113] = b113; + rl_relooper_add_block(rl, block_map[113]); + void *b114 = rl_new_block("code 114"); + block_map[114] = b114; + rl_relooper_add_block(rl, block_map[114]); + void *b115 = rl_new_block("code 115"); + block_map[115] = b115; + rl_relooper_add_block(rl, block_map[115]); + void *b116 = rl_new_block("code 116"); + block_map[116] = b116; + rl_relooper_add_block(rl, block_map[116]); + void *b117 = rl_new_block("code 117"); + block_map[117] = b117; + rl_relooper_add_block(rl, block_map[117]); + void *b118 = rl_new_block("code 118"); + block_map[118] = b118; + rl_relooper_add_block(rl, block_map[118]); + void *b119 = rl_new_block("code 119"); + block_map[119] = b119; + rl_relooper_add_block(rl, block_map[119]); + void *b120 = rl_new_block("code 120"); + block_map[120] = b120; + rl_relooper_add_block(rl, block_map[120]); + void *b121 = rl_new_block("code 121"); + block_map[121] = b121; + rl_relooper_add_block(rl, block_map[121]); + void *b122 = rl_new_block("code 122"); + block_map[122] = b122; + rl_relooper_add_block(rl, block_map[122]); + void *b123 = rl_new_block("code 123"); + block_map[123] = b123; + rl_relooper_add_block(rl, block_map[123]); + void *b124 = rl_new_block("code 124"); + block_map[124] = b124; + rl_relooper_add_block(rl, block_map[124]); + void *b125 = rl_new_block("code 125"); + block_map[125] = b125; + rl_relooper_add_block(rl, block_map[125]); + void *b126 = rl_new_block("code 126"); + block_map[126] = b126; + rl_relooper_add_block(rl, block_map[126]); + void *b127 = rl_new_block("code 127"); + block_map[127] = b127; + rl_relooper_add_block(rl, block_map[127]); + void *b128 = rl_new_block("code 128"); + block_map[128] = b128; + rl_relooper_add_block(rl, block_map[128]); + void *b129 = rl_new_block("code 129"); + block_map[129] = b129; + rl_relooper_add_block(rl, block_map[129]); + void *b130 = rl_new_block("code 130"); + block_map[130] = b130; + rl_relooper_add_block(rl, block_map[130]); + void *b131 = rl_new_block("code 131"); + block_map[131] = b131; + rl_relooper_add_block(rl, block_map[131]); + void *b132 = rl_new_block("code 132"); + block_map[132] = b132; + rl_relooper_add_block(rl, block_map[132]); + void *b133 = rl_new_block("code 133"); + block_map[133] = b133; + rl_relooper_add_block(rl, block_map[133]); + void *b134 = rl_new_block("code 134"); + block_map[134] = b134; + rl_relooper_add_block(rl, block_map[134]); + void *b135 = rl_new_block("code 135"); + block_map[135] = b135; + rl_relooper_add_block(rl, block_map[135]); + void *b136 = rl_new_block("code 136"); + block_map[136] = b136; + rl_relooper_add_block(rl, block_map[136]); + void *b137 = rl_new_block("code 137"); + block_map[137] = b137; + rl_relooper_add_block(rl, block_map[137]); + void *b138 = rl_new_block("code 138"); + block_map[138] = b138; + rl_relooper_add_block(rl, block_map[138]); + void *b139 = rl_new_block("code 139"); + block_map[139] = b139; + rl_relooper_add_block(rl, block_map[139]); + void *b140 = rl_new_block("code 140"); + block_map[140] = b140; + rl_relooper_add_block(rl, block_map[140]); + void *b141 = rl_new_block("code 141"); + block_map[141] = b141; + rl_relooper_add_block(rl, block_map[141]); + void *b142 = rl_new_block("code 142"); + block_map[142] = b142; + rl_relooper_add_block(rl, block_map[142]); + void *b143 = rl_new_block("code 143"); + block_map[143] = b143; + rl_relooper_add_block(rl, block_map[143]); + void *b144 = rl_new_block("code 144"); + block_map[144] = b144; + rl_relooper_add_block(rl, block_map[144]); + void *b145 = rl_new_block("code 145"); + block_map[145] = b145; + rl_relooper_add_block(rl, block_map[145]); + void *b146 = rl_new_block("code 146"); + block_map[146] = b146; + rl_relooper_add_block(rl, block_map[146]); + void *b147 = rl_new_block("code 147"); + block_map[147] = b147; + rl_relooper_add_block(rl, block_map[147]); + void *b148 = rl_new_block("code 148"); + block_map[148] = b148; + rl_relooper_add_block(rl, block_map[148]); + void *b149 = rl_new_block("code 149"); + block_map[149] = b149; + rl_relooper_add_block(rl, block_map[149]); + void *b150 = rl_new_block("code 150"); + block_map[150] = b150; + rl_relooper_add_block(rl, block_map[150]); + void *b151 = rl_new_block("code 151"); + block_map[151] = b151; + rl_relooper_add_block(rl, block_map[151]); + void *b152 = rl_new_block("code 152"); + block_map[152] = b152; + rl_relooper_add_block(rl, block_map[152]); + void *b153 = rl_new_block("code 153"); + block_map[153] = b153; + rl_relooper_add_block(rl, block_map[153]); + void *b154 = rl_new_block("code 154"); + block_map[154] = b154; + rl_relooper_add_block(rl, block_map[154]); + void *b155 = rl_new_block("code 155"); + block_map[155] = b155; + rl_relooper_add_block(rl, block_map[155]); + void *b156 = rl_new_block("code 156"); + block_map[156] = b156; + rl_relooper_add_block(rl, block_map[156]); + void *b157 = rl_new_block("code 157"); + block_map[157] = b157; + rl_relooper_add_block(rl, block_map[157]); + void *b158 = rl_new_block("code 158"); + block_map[158] = b158; + rl_relooper_add_block(rl, block_map[158]); + void *b159 = rl_new_block("code 159"); + block_map[159] = b159; + rl_relooper_add_block(rl, block_map[159]); + void *b160 = rl_new_block("code 160"); + block_map[160] = b160; + rl_relooper_add_block(rl, block_map[160]); + void *b161 = rl_new_block("code 161"); + block_map[161] = b161; + rl_relooper_add_block(rl, block_map[161]); + void *b162 = rl_new_block("code 162"); + block_map[162] = b162; + rl_relooper_add_block(rl, block_map[162]); + void *b163 = rl_new_block("code 163"); + block_map[163] = b163; + rl_relooper_add_block(rl, block_map[163]); + void *b164 = rl_new_block("code 164"); + block_map[164] = b164; + rl_relooper_add_block(rl, block_map[164]); + void *b165 = rl_new_block("code 165"); + block_map[165] = b165; + rl_relooper_add_block(rl, block_map[165]); + void *b166 = rl_new_block("code 166"); + block_map[166] = b166; + rl_relooper_add_block(rl, block_map[166]); + void *b167 = rl_new_block("code 167"); + block_map[167] = b167; + rl_relooper_add_block(rl, block_map[167]); + void *b168 = rl_new_block("code 168"); + block_map[168] = b168; + rl_relooper_add_block(rl, block_map[168]); + void *b169 = rl_new_block("code 169"); + block_map[169] = b169; + rl_relooper_add_block(rl, block_map[169]); + void *b170 = rl_new_block("code 170"); + block_map[170] = b170; + rl_relooper_add_block(rl, block_map[170]); + void *b171 = rl_new_block("code 171"); + block_map[171] = b171; + rl_relooper_add_block(rl, block_map[171]); + void *b172 = rl_new_block("code 172"); + block_map[172] = b172; + rl_relooper_add_block(rl, block_map[172]); + void *b173 = rl_new_block("code 173"); + block_map[173] = b173; + rl_relooper_add_block(rl, block_map[173]); + void *b174 = rl_new_block("code 174"); + block_map[174] = b174; + rl_relooper_add_block(rl, block_map[174]); + void *b175 = rl_new_block("code 175"); + block_map[175] = b175; + rl_relooper_add_block(rl, block_map[175]); + void *b176 = rl_new_block("code 176"); + block_map[176] = b176; + rl_relooper_add_block(rl, block_map[176]); + void *b177 = rl_new_block("code 177"); + block_map[177] = b177; + rl_relooper_add_block(rl, block_map[177]); + void *b178 = rl_new_block("code 178"); + block_map[178] = b178; + rl_relooper_add_block(rl, block_map[178]); + void *b179 = rl_new_block("code 179"); + block_map[179] = b179; + rl_relooper_add_block(rl, block_map[179]); + void *b180 = rl_new_block("code 180"); + block_map[180] = b180; + rl_relooper_add_block(rl, block_map[180]); + void *b181 = rl_new_block("code 181"); + block_map[181] = b181; + rl_relooper_add_block(rl, block_map[181]); + void *b182 = rl_new_block("code 182"); + block_map[182] = b182; + rl_relooper_add_block(rl, block_map[182]); + void *b183 = rl_new_block("code 183"); + block_map[183] = b183; + rl_relooper_add_block(rl, block_map[183]); + rl_block_add_branch_to(block_map[0], block_map[2], "uint(i4) >= uint(i5)", NULL); + rl_block_add_branch_to(block_map[0], block_map[1], NULL, NULL); + rl_block_add_branch_to(block_map[1], block_map[3], NULL, NULL); + rl_block_add_branch_to(block_map[2], block_map[3], NULL, NULL); + rl_block_add_branch_to(block_map[3], block_map[15], "i2 == 0", NULL); + rl_block_add_branch_to(block_map[3], block_map[4], NULL, NULL); + rl_block_add_branch_to(block_map[4], block_map[5], NULL, NULL); + rl_block_add_branch_to(block_map[5], block_map[7], "uint(i6) >= uint(i7)", NULL); + rl_block_add_branch_to(block_map[5], block_map[6], NULL, NULL); + rl_block_add_branch_to(block_map[6], block_map[8], NULL, NULL); + rl_block_add_branch_to(block_map[7], block_map[8], NULL, NULL); + rl_block_add_branch_to(block_map[8], block_map[10], "uint(i6) >= uint(i7)", NULL); + rl_block_add_branch_to(block_map[8], block_map[9], NULL, NULL); + rl_block_add_branch_to(block_map[9], block_map[11], NULL, NULL); + rl_block_add_branch_to(block_map[10], block_map[11], NULL, NULL); + rl_block_add_branch_to(block_map[11], block_map[13], "uint(i5) >= uint(i6)", NULL); + rl_block_add_branch_to(block_map[11], block_map[12], NULL, NULL); + rl_block_add_branch_to(block_map[12], block_map[14], NULL, NULL); + rl_block_add_branch_to(block_map[13], block_map[14], NULL, NULL); + rl_block_add_branch_to(block_map[14], block_map[5], "i2 != 0", NULL); + rl_block_add_branch_to(block_map[14], block_map[15], NULL, NULL); + rl_block_add_branch_to(block_map[15], block_map[17], "uint(i4) >= uint(i5)", NULL); + rl_block_add_branch_to(block_map[15], block_map[16], NULL, NULL); + rl_block_add_branch_to(block_map[16], block_map[18], NULL, NULL); + rl_block_add_branch_to(block_map[17], block_map[18], NULL, NULL); + rl_block_add_branch_to(block_map[18], block_map[102], "i2 == 0", NULL); + rl_block_add_branch_to(block_map[18], block_map[19], NULL, NULL); + rl_block_add_branch_to(block_map[19], block_map[20], NULL, NULL); + rl_block_add_branch_to(block_map[20], block_map[22], "uint(i5) >= uint(i6)", NULL); + rl_block_add_branch_to(block_map[20], block_map[21], NULL, NULL); + rl_block_add_branch_to(block_map[21], block_map[23], NULL, NULL); + rl_block_add_branch_to(block_map[22], block_map[23], NULL, NULL); + rl_block_add_branch_to(block_map[23], block_map[25], "uint(i5) >= uint(i6)", NULL); + rl_block_add_branch_to(block_map[23], block_map[24], NULL, NULL); + rl_block_add_branch_to(block_map[24], block_map[26], NULL, NULL); + rl_block_add_branch_to(block_map[25], block_map[26], NULL, NULL); + rl_block_add_branch_to(block_map[26], block_map[28], "uint(i5) >= uint(i6)", NULL); + rl_block_add_branch_to(block_map[26], block_map[27], NULL, NULL); + rl_block_add_branch_to(block_map[27], block_map[29], NULL, NULL); + rl_block_add_branch_to(block_map[28], block_map[29], NULL, NULL); + rl_block_add_branch_to(block_map[29], block_map[31], "uint(i5) >= uint(i6)", NULL); + rl_block_add_branch_to(block_map[29], block_map[30], NULL, NULL); + rl_block_add_branch_to(block_map[30], block_map[32], NULL, NULL); + rl_block_add_branch_to(block_map[31], block_map[32], NULL, NULL); + rl_block_add_branch_to(block_map[32], block_map[34], "uint(i5) >= uint(i6)", NULL); + rl_block_add_branch_to(block_map[32], block_map[33], NULL, NULL); + rl_block_add_branch_to(block_map[33], block_map[35], NULL, NULL); + rl_block_add_branch_to(block_map[34], block_map[35], NULL, NULL); + rl_block_add_branch_to(block_map[35], block_map[37], "uint(i5) >= uint(i6)", NULL); + rl_block_add_branch_to(block_map[35], block_map[36], NULL, NULL); + rl_block_add_branch_to(block_map[36], block_map[38], NULL, NULL); + rl_block_add_branch_to(block_map[37], block_map[38], NULL, NULL); + rl_block_add_branch_to(block_map[38], block_map[40], "uint(i5) >= uint(i6)", NULL); + rl_block_add_branch_to(block_map[38], block_map[39], NULL, NULL); + rl_block_add_branch_to(block_map[39], block_map[41], NULL, NULL); + rl_block_add_branch_to(block_map[40], block_map[41], NULL, NULL); + rl_block_add_branch_to(block_map[41], block_map[43], "uint(i5) >= uint(i6)", NULL); + rl_block_add_branch_to(block_map[41], block_map[42], NULL, NULL); + rl_block_add_branch_to(block_map[42], block_map[44], NULL, NULL); + rl_block_add_branch_to(block_map[43], block_map[44], NULL, NULL); + rl_block_add_branch_to(block_map[44], block_map[46], "uint(i5) >= uint(i6)", NULL); + rl_block_add_branch_to(block_map[44], block_map[45], NULL, NULL); + rl_block_add_branch_to(block_map[45], block_map[47], NULL, NULL); + rl_block_add_branch_to(block_map[46], block_map[47], NULL, NULL); + rl_block_add_branch_to(block_map[47], block_map[49], "uint(i5) >= uint(i6)", NULL); + rl_block_add_branch_to(block_map[47], block_map[48], NULL, NULL); + rl_block_add_branch_to(block_map[48], block_map[50], NULL, NULL); + rl_block_add_branch_to(block_map[49], block_map[50], NULL, NULL); + rl_block_add_branch_to(block_map[50], block_map[52], "uint(i5) >= uint(i6)", NULL); + rl_block_add_branch_to(block_map[50], block_map[51], NULL, NULL); + rl_block_add_branch_to(block_map[51], block_map[53], NULL, NULL); + rl_block_add_branch_to(block_map[52], block_map[53], NULL, NULL); + rl_block_add_branch_to(block_map[53], block_map[55], "uint(i5) >= uint(i6)", NULL); + rl_block_add_branch_to(block_map[53], block_map[54], NULL, NULL); + rl_block_add_branch_to(block_map[54], block_map[56], NULL, NULL); + rl_block_add_branch_to(block_map[55], block_map[56], NULL, NULL); + rl_block_add_branch_to(block_map[56], block_map[58], "uint(i5) >= uint(i6)", NULL); + rl_block_add_branch_to(block_map[56], block_map[57], NULL, NULL); + rl_block_add_branch_to(block_map[57], block_map[59], NULL, NULL); + rl_block_add_branch_to(block_map[58], block_map[59], NULL, NULL); + rl_block_add_branch_to(block_map[59], block_map[61], "uint(i5) >= uint(i6)", NULL); + rl_block_add_branch_to(block_map[59], block_map[60], NULL, NULL); + rl_block_add_branch_to(block_map[60], block_map[62], NULL, NULL); + rl_block_add_branch_to(block_map[61], block_map[62], NULL, NULL); + rl_block_add_branch_to(block_map[62], block_map[64], "uint(i5) >= uint(i6)", NULL); + rl_block_add_branch_to(block_map[62], block_map[63], NULL, NULL); + rl_block_add_branch_to(block_map[63], block_map[65], NULL, NULL); + rl_block_add_branch_to(block_map[64], block_map[65], NULL, NULL); + rl_block_add_branch_to(block_map[65], block_map[67], "uint(i5) >= uint(i6)", NULL); + rl_block_add_branch_to(block_map[65], block_map[66], NULL, NULL); + rl_block_add_branch_to(block_map[66], block_map[68], NULL, NULL); + rl_block_add_branch_to(block_map[67], block_map[68], NULL, NULL); + rl_block_add_branch_to(block_map[68], block_map[70], "uint(i5) >= uint(i6)", NULL); + rl_block_add_branch_to(block_map[68], block_map[69], NULL, NULL); + rl_block_add_branch_to(block_map[69], block_map[71], NULL, NULL); + rl_block_add_branch_to(block_map[70], block_map[71], NULL, NULL); + rl_block_add_branch_to(block_map[71], block_map[73], "uint(i5) >= uint(i6)", NULL); + rl_block_add_branch_to(block_map[71], block_map[72], NULL, NULL); + rl_block_add_branch_to(block_map[72], block_map[74], NULL, NULL); + rl_block_add_branch_to(block_map[73], block_map[74], NULL, NULL); + rl_block_add_branch_to(block_map[74], block_map[76], "uint(i5) >= uint(i6)", NULL); + rl_block_add_branch_to(block_map[74], block_map[75], NULL, NULL); + rl_block_add_branch_to(block_map[75], block_map[77], NULL, NULL); + rl_block_add_branch_to(block_map[76], block_map[77], NULL, NULL); + rl_block_add_branch_to(block_map[77], block_map[79], "uint(i5) >= uint(i6)", NULL); + rl_block_add_branch_to(block_map[77], block_map[78], NULL, NULL); + rl_block_add_branch_to(block_map[78], block_map[80], NULL, NULL); + rl_block_add_branch_to(block_map[79], block_map[80], NULL, NULL); + rl_block_add_branch_to(block_map[80], block_map[82], "uint(i5) >= uint(i6)", NULL); + rl_block_add_branch_to(block_map[80], block_map[81], NULL, NULL); + rl_block_add_branch_to(block_map[81], block_map[83], NULL, NULL); + rl_block_add_branch_to(block_map[82], block_map[83], NULL, NULL); + rl_block_add_branch_to(block_map[83], block_map[85], "uint(i5) >= uint(i6)", NULL); + rl_block_add_branch_to(block_map[83], block_map[84], NULL, NULL); + rl_block_add_branch_to(block_map[84], block_map[86], NULL, NULL); + rl_block_add_branch_to(block_map[85], block_map[86], NULL, NULL); + rl_block_add_branch_to(block_map[86], block_map[88], "uint(i5) >= uint(i6)", NULL); + rl_block_add_branch_to(block_map[86], block_map[87], NULL, NULL); + rl_block_add_branch_to(block_map[87], block_map[89], NULL, NULL); + rl_block_add_branch_to(block_map[88], block_map[89], NULL, NULL); + rl_block_add_branch_to(block_map[89], block_map[91], "uint(i5) >= uint(i6)", NULL); + rl_block_add_branch_to(block_map[89], block_map[90], NULL, NULL); + rl_block_add_branch_to(block_map[90], block_map[92], NULL, NULL); + rl_block_add_branch_to(block_map[91], block_map[92], NULL, NULL); + rl_block_add_branch_to(block_map[92], block_map[94], "uint(i5) >= uint(i6)", NULL); + rl_block_add_branch_to(block_map[92], block_map[93], NULL, NULL); + rl_block_add_branch_to(block_map[93], block_map[95], NULL, NULL); + rl_block_add_branch_to(block_map[94], block_map[95], NULL, NULL); + rl_block_add_branch_to(block_map[95], block_map[97], "uint(i5) >= uint(i6)", NULL); + rl_block_add_branch_to(block_map[95], block_map[96], NULL, NULL); + rl_block_add_branch_to(block_map[96], block_map[98], NULL, NULL); + rl_block_add_branch_to(block_map[97], block_map[98], NULL, NULL); + rl_block_add_branch_to(block_map[98], block_map[100], "uint(i5) >= uint(i6)", NULL); + rl_block_add_branch_to(block_map[98], block_map[99], NULL, NULL); + rl_block_add_branch_to(block_map[99], block_map[101], NULL, NULL); + rl_block_add_branch_to(block_map[100], block_map[101], NULL, NULL); + rl_block_add_branch_to(block_map[101], block_map[20], "i2 != 0", NULL); + rl_block_add_branch_to(block_map[101], block_map[102], NULL, NULL); + rl_block_add_branch_to(block_map[102], block_map[104], "uint(i4) >= uint(i5)", NULL); + rl_block_add_branch_to(block_map[102], block_map[103], NULL, NULL); + rl_block_add_branch_to(block_map[103], block_map[105], NULL, NULL); + rl_block_add_branch_to(block_map[104], block_map[105], NULL, NULL); + rl_block_add_branch_to(block_map[105], block_map[168], "i2 == 0", NULL); + rl_block_add_branch_to(block_map[105], block_map[106], NULL, NULL); + rl_block_add_branch_to(block_map[106], block_map[107], NULL, NULL); + rl_block_add_branch_to(block_map[107], block_map[109], "uint(i5) >= uint(i6)", NULL); + rl_block_add_branch_to(block_map[107], block_map[108], NULL, NULL); + rl_block_add_branch_to(block_map[108], block_map[110], NULL, NULL); + rl_block_add_branch_to(block_map[109], block_map[110], NULL, NULL); + rl_block_add_branch_to(block_map[110], block_map[112], "uint(i5) >= uint(i6)", NULL); + rl_block_add_branch_to(block_map[110], block_map[111], NULL, NULL); + rl_block_add_branch_to(block_map[111], block_map[113], NULL, NULL); + rl_block_add_branch_to(block_map[112], block_map[113], NULL, NULL); + rl_block_add_branch_to(block_map[113], block_map[115], "uint(i5) >= uint(i6)", NULL); + rl_block_add_branch_to(block_map[113], block_map[114], NULL, NULL); + rl_block_add_branch_to(block_map[114], block_map[116], NULL, NULL); + rl_block_add_branch_to(block_map[115], block_map[116], NULL, NULL); + rl_block_add_branch_to(block_map[116], block_map[118], "uint(i5) >= uint(i6)", NULL); + rl_block_add_branch_to(block_map[116], block_map[117], NULL, NULL); + rl_block_add_branch_to(block_map[117], block_map[119], NULL, NULL); + rl_block_add_branch_to(block_map[118], block_map[119], NULL, NULL); + rl_block_add_branch_to(block_map[119], block_map[121], "uint(i5) >= uint(i6)", NULL); + rl_block_add_branch_to(block_map[119], block_map[120], NULL, NULL); + rl_block_add_branch_to(block_map[120], block_map[122], NULL, NULL); + rl_block_add_branch_to(block_map[121], block_map[122], NULL, NULL); + rl_block_add_branch_to(block_map[122], block_map[124], "uint(i5) >= uint(i6)", NULL); + rl_block_add_branch_to(block_map[122], block_map[123], NULL, NULL); + rl_block_add_branch_to(block_map[123], block_map[125], NULL, NULL); + rl_block_add_branch_to(block_map[124], block_map[125], NULL, NULL); + rl_block_add_branch_to(block_map[125], block_map[127], "uint(i5) >= uint(i6)", NULL); + rl_block_add_branch_to(block_map[125], block_map[126], NULL, NULL); + rl_block_add_branch_to(block_map[126], block_map[128], NULL, NULL); + rl_block_add_branch_to(block_map[127], block_map[128], NULL, NULL); + rl_block_add_branch_to(block_map[128], block_map[130], "uint(i5) >= uint(i6)", NULL); + rl_block_add_branch_to(block_map[128], block_map[129], NULL, NULL); + rl_block_add_branch_to(block_map[129], block_map[131], NULL, NULL); + rl_block_add_branch_to(block_map[130], block_map[131], NULL, NULL); + rl_block_add_branch_to(block_map[131], block_map[133], "uint(i5) >= uint(i6)", NULL); + rl_block_add_branch_to(block_map[131], block_map[132], NULL, NULL); + rl_block_add_branch_to(block_map[132], block_map[134], NULL, NULL); + rl_block_add_branch_to(block_map[133], block_map[134], NULL, NULL); + rl_block_add_branch_to(block_map[134], block_map[136], "uint(i5) >= uint(i6)", NULL); + rl_block_add_branch_to(block_map[134], block_map[135], NULL, NULL); + rl_block_add_branch_to(block_map[135], block_map[137], NULL, NULL); + rl_block_add_branch_to(block_map[136], block_map[137], NULL, NULL); + rl_block_add_branch_to(block_map[137], block_map[139], "uint(i5) >= uint(i6)", NULL); + rl_block_add_branch_to(block_map[137], block_map[138], NULL, NULL); + rl_block_add_branch_to(block_map[138], block_map[140], NULL, NULL); + rl_block_add_branch_to(block_map[139], block_map[140], NULL, NULL); + rl_block_add_branch_to(block_map[140], block_map[142], "uint(i5) >= uint(i6)", NULL); + rl_block_add_branch_to(block_map[140], block_map[141], NULL, NULL); + rl_block_add_branch_to(block_map[141], block_map[143], NULL, NULL); + rl_block_add_branch_to(block_map[142], block_map[143], NULL, NULL); + rl_block_add_branch_to(block_map[143], block_map[145], "uint(i5) >= uint(i6)", NULL); + rl_block_add_branch_to(block_map[143], block_map[144], NULL, NULL); + rl_block_add_branch_to(block_map[144], block_map[146], NULL, NULL); + rl_block_add_branch_to(block_map[145], block_map[146], NULL, NULL); + rl_block_add_branch_to(block_map[146], block_map[148], "uint(i5) >= uint(i6)", NULL); + rl_block_add_branch_to(block_map[146], block_map[147], NULL, NULL); + rl_block_add_branch_to(block_map[147], block_map[149], NULL, NULL); + rl_block_add_branch_to(block_map[148], block_map[149], NULL, NULL); + rl_block_add_branch_to(block_map[149], block_map[151], "uint(i5) >= uint(i6)", NULL); + rl_block_add_branch_to(block_map[149], block_map[150], NULL, NULL); + rl_block_add_branch_to(block_map[150], block_map[152], NULL, NULL); + rl_block_add_branch_to(block_map[151], block_map[152], NULL, NULL); + rl_block_add_branch_to(block_map[152], block_map[154], "uint(i5) >= uint(i6)", NULL); + rl_block_add_branch_to(block_map[152], block_map[153], NULL, NULL); + rl_block_add_branch_to(block_map[153], block_map[155], NULL, NULL); + rl_block_add_branch_to(block_map[154], block_map[155], NULL, NULL); + rl_block_add_branch_to(block_map[155], block_map[157], "uint(i5) >= uint(i6)", NULL); + rl_block_add_branch_to(block_map[155], block_map[156], NULL, NULL); + rl_block_add_branch_to(block_map[156], block_map[158], NULL, NULL); + rl_block_add_branch_to(block_map[157], block_map[158], NULL, NULL); + rl_block_add_branch_to(block_map[158], block_map[160], "uint(i5) >= uint(i6)", NULL); + rl_block_add_branch_to(block_map[158], block_map[159], NULL, NULL); + rl_block_add_branch_to(block_map[159], block_map[161], NULL, NULL); + rl_block_add_branch_to(block_map[160], block_map[161], NULL, NULL); + rl_block_add_branch_to(block_map[161], block_map[163], "uint(i5) >= uint(i6)", NULL); + rl_block_add_branch_to(block_map[161], block_map[162], NULL, NULL); + rl_block_add_branch_to(block_map[162], block_map[164], NULL, NULL); + rl_block_add_branch_to(block_map[163], block_map[164], NULL, NULL); + rl_block_add_branch_to(block_map[164], block_map[166], "uint(i5) >= uint(i6)", NULL); + rl_block_add_branch_to(block_map[164], block_map[165], NULL, NULL); + rl_block_add_branch_to(block_map[165], block_map[167], NULL, NULL); + rl_block_add_branch_to(block_map[166], block_map[167], NULL, NULL); + rl_block_add_branch_to(block_map[167], block_map[107], "i2 != 0", NULL); + rl_block_add_branch_to(block_map[167], block_map[168], NULL, NULL); + rl_block_add_branch_to(block_map[168], block_map[170], "uint(i4) >= uint(i5)", NULL); + rl_block_add_branch_to(block_map[168], block_map[169], NULL, NULL); + rl_block_add_branch_to(block_map[169], block_map[171], NULL, NULL); + rl_block_add_branch_to(block_map[170], block_map[171], NULL, NULL); + rl_block_add_branch_to(block_map[171], block_map[183], "i2 == 0", NULL); + rl_block_add_branch_to(block_map[171], block_map[172], NULL, NULL); + rl_block_add_branch_to(block_map[172], block_map[173], NULL, NULL); + rl_block_add_branch_to(block_map[173], block_map[175], "uint(i5) >= uint(i6)", NULL); + rl_block_add_branch_to(block_map[173], block_map[174], NULL, NULL); + rl_block_add_branch_to(block_map[174], block_map[176], NULL, NULL); + rl_block_add_branch_to(block_map[175], block_map[176], NULL, NULL); + rl_block_add_branch_to(block_map[176], block_map[178], "uint(i5) >= uint(i6)", NULL); + rl_block_add_branch_to(block_map[176], block_map[177], NULL, NULL); + rl_block_add_branch_to(block_map[177], block_map[179], NULL, NULL); + rl_block_add_branch_to(block_map[178], block_map[179], NULL, NULL); + rl_block_add_branch_to(block_map[179], block_map[181], "uint(i4) >= uint(i5)", NULL); + rl_block_add_branch_to(block_map[179], block_map[180], NULL, NULL); + rl_block_add_branch_to(block_map[180], block_map[182], NULL, NULL); + rl_block_add_branch_to(block_map[181], block_map[182], NULL, NULL); + rl_block_add_branch_to(block_map[182], block_map[173], "i2 != 0", NULL); + rl_block_add_branch_to(block_map[182], block_map[183], NULL, NULL); + rl_relooper_calculate(rl, block_map[0]); + rl_relooper_render(rl); + rl_delete_relooper(rl); + puts(buffer); + return 0; +} + diff --git a/src/relooper/test_inf.txt b/src/relooper/test_inf.txt new file mode 100644 index 0000000000000..2edfc7604c3c0 --- /dev/null +++ b/src/relooper/test_inf.txt @@ -0,0 +1,392 @@ +code 0 +if (uint(i4) >= uint(i5)) { + code 2 +} else { + code 1 +} +code 3 +L5: do { + if (!(i2 == 0)) { + code 4 + while(1) { + code 5 + if (uint(i6) >= uint(i7)) { + code 7 + } else { + code 6 + } + code 8 + if (uint(i6) >= uint(i7)) { + code 10 + } else { + code 9 + } + code 11 + if (uint(i5) >= uint(i6)) { + code 13 + } else { + code 12 + } + code 14 + if (!(i2 != 0)) { + break L5; + } + } + } +} while(0); +code 15 +if (uint(i4) >= uint(i5)) { + code 17 +} else { + code 16 +} +code 18 +L26: do { + if (!(i2 == 0)) { + code 19 + while(1) { + code 20 + if (uint(i5) >= uint(i6)) { + code 22 + } else { + code 21 + } + code 23 + if (uint(i5) >= uint(i6)) { + code 25 + } else { + code 24 + } + code 26 + if (uint(i5) >= uint(i6)) { + code 28 + } else { + code 27 + } + code 29 + if (uint(i5) >= uint(i6)) { + code 31 + } else { + code 30 + } + code 32 + if (uint(i5) >= uint(i6)) { + code 34 + } else { + code 33 + } + code 35 + if (uint(i5) >= uint(i6)) { + code 37 + } else { + code 36 + } + code 38 + if (uint(i5) >= uint(i6)) { + code 40 + } else { + code 39 + } + code 41 + if (uint(i5) >= uint(i6)) { + code 43 + } else { + code 42 + } + code 44 + if (uint(i5) >= uint(i6)) { + code 46 + } else { + code 45 + } + code 47 + if (uint(i5) >= uint(i6)) { + code 49 + } else { + code 48 + } + code 50 + if (uint(i5) >= uint(i6)) { + code 52 + } else { + code 51 + } + code 53 + if (uint(i5) >= uint(i6)) { + code 55 + } else { + code 54 + } + code 56 + if (uint(i5) >= uint(i6)) { + code 58 + } else { + code 57 + } + code 59 + if (uint(i5) >= uint(i6)) { + code 61 + } else { + code 60 + } + code 62 + if (uint(i5) >= uint(i6)) { + code 64 + } else { + code 63 + } + code 65 + if (uint(i5) >= uint(i6)) { + code 67 + } else { + code 66 + } + code 68 + if (uint(i5) >= uint(i6)) { + code 70 + } else { + code 69 + } + code 71 + if (uint(i5) >= uint(i6)) { + code 73 + } else { + code 72 + } + code 74 + if (uint(i5) >= uint(i6)) { + code 76 + } else { + code 75 + } + code 77 + if (uint(i5) >= uint(i6)) { + code 79 + } else { + code 78 + } + code 80 + if (uint(i5) >= uint(i6)) { + code 82 + } else { + code 81 + } + code 83 + if (uint(i5) >= uint(i6)) { + code 85 + } else { + code 84 + } + code 86 + if (uint(i5) >= uint(i6)) { + code 88 + } else { + code 87 + } + code 89 + if (uint(i5) >= uint(i6)) { + code 91 + } else { + code 90 + } + code 92 + if (uint(i5) >= uint(i6)) { + code 94 + } else { + code 93 + } + code 95 + if (uint(i5) >= uint(i6)) { + code 97 + } else { + code 96 + } + code 98 + if (uint(i5) >= uint(i6)) { + code 100 + } else { + code 99 + } + code 101 + if (!(i2 != 0)) { + break L26; + } + } + } +} while(0); +code 102 +if (uint(i4) >= uint(i5)) { + code 104 +} else { + code 103 +} +code 105 +L143: do { + if (!(i2 == 0)) { + code 106 + while(1) { + code 107 + if (uint(i5) >= uint(i6)) { + code 109 + } else { + code 108 + } + code 110 + if (uint(i5) >= uint(i6)) { + code 112 + } else { + code 111 + } + code 113 + if (uint(i5) >= uint(i6)) { + code 115 + } else { + code 114 + } + code 116 + if (uint(i5) >= uint(i6)) { + code 118 + } else { + code 117 + } + code 119 + if (uint(i5) >= uint(i6)) { + code 121 + } else { + code 120 + } + code 122 + if (uint(i5) >= uint(i6)) { + code 124 + } else { + code 123 + } + code 125 + if (uint(i5) >= uint(i6)) { + code 127 + } else { + code 126 + } + code 128 + if (uint(i5) >= uint(i6)) { + code 130 + } else { + code 129 + } + code 131 + if (uint(i5) >= uint(i6)) { + code 133 + } else { + code 132 + } + code 134 + if (uint(i5) >= uint(i6)) { + code 136 + } else { + code 135 + } + code 137 + if (uint(i5) >= uint(i6)) { + code 139 + } else { + code 138 + } + code 140 + if (uint(i5) >= uint(i6)) { + code 142 + } else { + code 141 + } + code 143 + if (uint(i5) >= uint(i6)) { + code 145 + } else { + code 144 + } + code 146 + if (uint(i5) >= uint(i6)) { + code 148 + } else { + code 147 + } + code 149 + if (uint(i5) >= uint(i6)) { + code 151 + } else { + code 150 + } + code 152 + if (uint(i5) >= uint(i6)) { + code 154 + } else { + code 153 + } + code 155 + if (uint(i5) >= uint(i6)) { + code 157 + } else { + code 156 + } + code 158 + if (uint(i5) >= uint(i6)) { + code 160 + } else { + code 159 + } + code 161 + if (uint(i5) >= uint(i6)) { + code 163 + } else { + code 162 + } + code 164 + if (uint(i5) >= uint(i6)) { + code 166 + } else { + code 165 + } + code 167 + if (!(i2 != 0)) { + break L143; + } + } + } +} while(0); +code 168 +if (uint(i4) >= uint(i5)) { + code 170 +} else { + code 169 +} +code 171 +if (i2 == 0) { + code 183 +} else { + code 172 + while(1) { + code 173 + if (uint(i5) >= uint(i6)) { + code 175 + } else { + code 174 + } + code 176 + if (uint(i5) >= uint(i6)) { + code 178 + } else { + code 177 + } + code 179 + if (uint(i4) >= uint(i5)) { + code 181 + } else { + code 180 + } + code 182 + if (!(i2 != 0)) { + break; + } + } + code 183 +} + diff --git a/src/relooper/testit.sh b/src/relooper/testit.sh new file mode 100755 index 0000000000000..28413c0de545c --- /dev/null +++ b/src/relooper/testit.sh @@ -0,0 +1,60 @@ +echo "test" +./test &> test.out +diff -U 5 test.txt test.out + +echo "test 2" +./test2 &> test2.out +diff -U 5 test2.txt test2.out + +echo "test 3" +./test3 &> test3.out +diff -U 5 test3.txt test3.out + +echo "test debug" +./test_debug &> test_debug.out +diff -U 5 test_debug.txt test_debug.out + +echo "test dead" +./test_dead &> test_dead.out +diff -U 5 test_dead.txt test_dead.out + +echo "test 4" +./test4 &> test4.out +diff -U 5 test4.txt test4.out + +echo "test 5" +./test5 &> test5.out +diff -U 5 test5.txt test5.out + +echo "test 6" +./test6 &> test6.out +diff -U 5 test6.txt test6.out + +echo "test inf" +./test_inf &> test_inf.out +diff -U 5 test_inf.txt test_inf.out + +echo "test fuzz1" +./test_fuzz1 &> test_fuzz1.out +diff -U 5 test_fuzz1.txt test_fuzz1.out + +echo "test fuzz2" +./test_fuzz2 &> test_fuzz2.out +diff -U 5 test_fuzz2.txt test_fuzz2.out + +echo "test fuzz3" +./test_fuzz3 &> test_fuzz3.out +diff -U 5 test_fuzz3.txt test_fuzz3.out + +echo "test fuzz4" +./test_fuzz4 &> test_fuzz4.out +diff -U 5 test_fuzz4.txt test_fuzz4.out + +echo "test fuzz5" +./test_fuzz5 &> test_fuzz5.out +diff -U 5 test_fuzz5.txt test_fuzz5.out + +echo "test fuzz6" +./test_fuzz6 &> test_fuzz6.out +diff -U 5 test_fuzz6.txt test_fuzz6.out + diff --git a/src/relooper/updateit.sh b/src/relooper/updateit.sh new file mode 100755 index 0000000000000..91ccd3ab2c024 --- /dev/null +++ b/src/relooper/updateit.sh @@ -0,0 +1,16 @@ +./test &> test.txt +./test2 &> test2.txt +./test3 &> test3.txt +./test_debug &> test_debug.txt +./test_dead &> test_dead.txt +./test4 &> test4.txt +./test5 &> test5.txt +./test6 &> test6.txt +./test_inf &> test_inf.txt +./test_fuzz1 &> test_fuzz1.txt +./test_fuzz2 &> test_fuzz2.txt +./test_fuzz3 &> test_fuzz3.txt +./test_fuzz4 &> test_fuzz4.txt +./test_fuzz5 &> test_fuzz5.txt +./test_fuzz6 &> test_fuzz6.txt + From 72e1ce8b4bfa082a72f154e4ca4a2f6ba504db5b Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sun, 11 Nov 2012 10:18:20 -0800 Subject: [PATCH 2/6] use internal relooper sources --- tests/runner.py | 2 -- tools/shared.py | 17 ++--------------- 2 files changed, 2 insertions(+), 17 deletions(-) diff --git a/tests/runner.py b/tests/runner.py index 413b27f9ccaef..b67d068edbf54 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -10168,8 +10168,6 @@ def test_relooper(self): output = '\n'.join(output) assert ('bootstrapping relooper succeeded' in output) == (i == 2), 'only bootstrap on first O2: ' + output assert os.path.exists(RELOOPER) == (i >= 2), 'have relooper on O2: ' + output - assert (' checking out' in output) == (i == 2 and phase == 0), 'check out the code on first O2, and if no dir already present: ' + output - assert (' updating' in output) == (i == 2 and phase == 1), 'when have relooper dir, just update: ' + output assert ('L2 : do {' in open('a.out.js').read()) == (i >= 2), 'reloop code on O2: ' + output else: diff --git a/tools/shared.py b/tools/shared.py index f3e34c85946b4..b5fd671fec1c4 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -1032,19 +1032,7 @@ def ensure_relooper(): print >> sys.stderr, '=======================================' print >> sys.stderr, 'bootstrapping relooper...' Cache.ensure() - RELOOPER_DIR = os.path.join(Cache.dirname, 'relooper') - currdir = os.getcwd() - if not os.path.exists(RELOOPER_DIR): - # check out relooper - os.chdir(os.path.dirname(RELOOPER_DIR)) - print >> sys.stderr, ' checking out', os.getcwd() - execute(['git', 'clone', 'git://github.com/kripken/Relooper.git', os.path.basename(RELOOPER_DIR)]) - assert os.path.exists(RELOOPER_DIR) - else: - # update - print >> sys.stderr, ' updating' - os.chdir(RELOOPER_DIR) - execute(['git', 'pull', '-u'], stdout=None if DEBUG else PIPE, stderr=None if DEBUG else PIPE) + RELOOPER_DIR = path_from_root('src', 'relooper') def make(opt_level): raw = RELOOPER + '.raw.js' @@ -1067,9 +1055,8 @@ def make(opt_level): print >> sys.stderr, '=======================================' ok = True finally: - os.chdir(currdir) if not ok: - print >> sys.stderr, 'bootstrapping relooper failed. You may need to manually create src/relooper.js, by checking out the Relooper project ( https://github.com/kripken/Relooper ) and building in the emscripten/ dir.' + print >> sys.stderr, 'bootstrapping relooper failed. You may need to manually create src/relooper.js by compiling it, see src/relooper/emscripten' 1/0 # Permanent cache for dlmalloc and stdlibc++ From 87acef9548f70a42c5a79a1037b3cc36aeb3a08c Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sun, 11 Nov 2012 10:38:16 -0800 Subject: [PATCH 3/6] allow skipping tests in test runner with skip:SUITE.TEST --- tests/runner.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/runner.py b/tests/runner.py index b67d068edbf54..3014fe9affac3 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -78,6 +78,9 @@ class RunnerCore(unittest.TestCase): stderr_redirect = STDOUT # This avoids cluttering the test runner output, which is stderr too, with compiler warnings etc. # Change this to None to get stderr reporting, for debugging purposes + def skipme(self): # used by tests we ask on the commandline to be skipped, see right before call to unittest.main + return self.skip('requested to be skipped') + def setUp(self): global Settings Settings.reset() @@ -10187,6 +10190,17 @@ def test_relooper(self): elif len(JS_ENGINES) < total_engines: print 'WARNING: Not all the JS engines in JS_ENGINES appears to work, ignoring those.' + # Skip requested tests + + for i in range(len(sys.argv)): + arg = sys.argv[i] + if arg.startswith('skip:'): + which = arg.split('skip:')[1] + print >> sys.stderr, 'will skip "%s"' % which + exec(which + ' = RunnerCore.skipme') + sys.argv[i] = '' + sys.argv = filter(lambda arg: arg, sys.argv) + # Go unittest.main() From b328775c6402e477a03abfb3b9c61968c8f5ee6a Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sun, 11 Nov 2012 10:43:20 -0800 Subject: [PATCH 4/6] hide some ugly output in test_local_link --- tests/runner.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/runner.py b/tests/runner.py index 3014fe9affac3..7523036b6cf8e 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -7567,7 +7567,7 @@ def test_local_link(self): ''') Popen(['python', EMCC, os.path.join(self.get_dir(), 'libfile.cpp'), '-o', 'libfile.so']).communicate() - Popen(['python', EMCC, os.path.join(self.get_dir(), 'main.cpp'), os.path.join(self.get_dir(), 'subdir', 'libfile.so'), '-L.']).communicate() + Popen(['python', EMCC, os.path.join(self.get_dir(), 'main.cpp'), os.path.join(self.get_dir(), 'subdir', 'libfile.so'), '-L.'], stderr=PIPE).communicate() self.assertContained('hello from lib', run_js(os.path.join(self.get_dir(), 'a.out.js'))) def test_runtimelink_multi(self): From 6545bd5cb7dbbe22067a7688854d33ff7b513763 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sun, 11 Nov 2012 12:22:49 -0800 Subject: [PATCH 5/6] optimize unbalanced 2-multiple shapes in relooper, prevent unnecessary nesting when the smaller is a dead end --- src/relooper/Relooper.cpp | 43 ++++++++++++++++++++++++++++++ src/relooper/test.cpp | 7 +++-- src/relooper/test.txt | 32 +++++++++++++++------- src/relooper/test_fuzz1.txt | 43 ++++++++++++------------------ src/relooper/test_fuzz2.txt | 9 +++---- src/relooper/test_fuzz4.txt | 19 +++++++------ src/relooper/test_fuzz6.txt | 53 ++++++++++++++++--------------------- src/relooper/test_inf.txt | 51 +++++++++++++++++------------------ 8 files changed, 146 insertions(+), 111 deletions(-) diff --git a/src/relooper/Relooper.cpp b/src/relooper/Relooper.cpp index f16055c0afb98..933fda966c77f 100644 --- a/src/relooper/Relooper.cpp +++ b/src/relooper/Relooper.cpp @@ -750,6 +750,49 @@ void Relooper::Calculate(Block *Entry) { } } + // As an optimization, if we have 2 independent groups, and one is a small dead end, we can handle only that dead end. + // The other then becomes a Next - without nesting in the code and recursion in the analysis. + // TODO: if the larger is the only dead end, handle that too + // TODO: handle >2 groups + // TODO: handle not just dead ends, but also that do not branch to the NextEntries. However, must be careful + // there since we create a Next, and that Next can prevent eliminating a break (since we no longer + // naturally reach the same place), which may necessitate a one-time loop, which makes the unnesting + // pointless. + if (IndependentGroups.size() == 2) { + // Find the smaller one + BlockBlockSetMap::iterator iter = IndependentGroups.begin(); + Block *SmallEntry = iter->first; + int SmallSize = iter->second.size(); + iter++; + Block *LargeEntry = iter->first; + int LargeSize = iter->second.size(); + if (SmallSize != LargeSize) { // ignore the case where they are identical - keep things symmetrical there + if (SmallSize > LargeSize) { + Block *Temp = SmallEntry; + SmallEntry = LargeEntry; + LargeEntry = Temp; // Note: we did not flip the Sizes too, they are now invalid. TODO: use the smaller size as a limit? + } + // Check if dead end + bool DeadEnd = true; + BlockSet &SmallGroup = IndependentGroups[SmallEntry]; + for (BlockSet::iterator iter = SmallGroup.begin(); iter != SmallGroup.end(); iter++) { + Block *Curr = *iter; + for (BlockBranchMap::iterator iter = Curr->BranchesOut.begin(); iter != Curr->BranchesOut.end(); iter++) { + Block *Target = iter->first; + if (SmallGroup.find(Target) == SmallGroup.end()) { + DeadEnd = false; + break; + } + } + if (!DeadEnd) break; + } + if (DeadEnd) { + PrintDebug("Removing nesting by not handling large group because small group is dead end\n"); + IndependentGroups.erase(LargeEntry); + } + } + } + PrintDebug("Handleable independent groups: %d\n", IndependentGroups.size()); if (IndependentGroups.size() > 0) { diff --git a/src/relooper/test.cpp b/src/relooper/test.cpp index 0d029216b2bf1..4275941b7478a 100644 --- a/src/relooper/test.cpp +++ b/src/relooper/test.cpp @@ -160,7 +160,7 @@ int main() { puts(buffer); } -/* + if (1) { Relooper::SetOutputBuffer(buffer, sizeof(buffer)); @@ -168,11 +168,11 @@ int main() { Block *b_a = new Block("// block A\n"); Block *b_b = new Block("// block B\n"); - Block *b_c = new Block("// block C\n"); + Block *b_c = new Block("return C;\n"); Block *b_d = new Block("// block D\n"); b_a->AddBranchTo(b_b, "check == 10"); - b_a->AddBranchTo(b_c, NULL); + b_a->AddBranchTo(b_c, NULL); // c is a dead end b_b->AddBranchTo(b_d, NULL); @@ -190,6 +190,5 @@ int main() { puts(buffer); } -*/ } diff --git a/src/relooper/test.txt b/src/relooper/test.txt index ff4ada2455925..12d0ef39b06ad 100644 --- a/src/relooper/test.txt +++ b/src/relooper/test.txt @@ -59,24 +59,21 @@ while(1) { } // code 3 if ($6) { - label = 14; break; } else { var $i_0 = $7;var $x_0 = $5; } } -if (label == 14) { - // code 4 - if ($10) { - // code 5 - } - // code 6 - var $x_1 = $13; +if (label == 18) { // code 7 } -else if (label == 18) { - // code 7 +// code 4 +if ($10) { + // code 5 } +// code 6 +var $x_1 = $13; +// code 7 @@ -97,3 +94,18 @@ if (chak()) { // block D } + + +-- Unbalanced with a dead end -- + + + +// block A +if (!(check == 10)) { + return C; +} +while(1) { + // block B + // block D +} + diff --git a/src/relooper/test_fuzz1.txt b/src/relooper/test_fuzz1.txt index 63bbee0c01563..5122257e5f884 100644 --- a/src/relooper/test_fuzz1.txt +++ b/src/relooper/test_fuzz1.txt @@ -8,37 +8,28 @@ do { print(7); state = check(); label = 3; break; - } else { - label = 2; } } while(0); L5: while(1) { - if (label == 2) { - label = 0; - print(1); state = check(); - while(1) { - print(3); state = check(); - if (!(state == 8)) { - label = 2; - continue L5; - } - print(8); state = check(); - if (!(state == 4)) { - label = 3; - continue L5; - } - print(4); state = check(); - if (!(state == 3)) { - label = 2; - continue L5; - } - } - } - else if (label == 3) { + if (label == 3) { label = 0; print(2); state = check(); - label = 2; - continue; + } + print(1); state = check(); + while(1) { + print(3); state = check(); + if (!(state == 8)) { + continue L5; + } + print(8); state = check(); + if (!(state == 4)) { + label = 3; + continue L5; + } + print(4); state = check(); + if (!(state == 3)) { + continue L5; + } } } diff --git a/src/relooper/test_fuzz2.txt b/src/relooper/test_fuzz2.txt index c48c6b6ca91d9..572e819de2ed7 100644 --- a/src/relooper/test_fuzz2.txt +++ b/src/relooper/test_fuzz2.txt @@ -5,10 +5,9 @@ if (state == 1) { while(1) { print(1); state = check(); } -} else { - while(1) { - print(3); state = check(); - print(2); state = check(); - } +} +while(1) { + print(3); state = check(); + print(2); state = check(); } diff --git a/src/relooper/test_fuzz4.txt b/src/relooper/test_fuzz4.txt index 5bb219f4af6be..05a70582a2554 100644 --- a/src/relooper/test_fuzz4.txt +++ b/src/relooper/test_fuzz4.txt @@ -5,16 +5,15 @@ if (state == 2) { while(1) { print(2); state = check(); } -} else { - while(1) { - print(4); state = check(); - if (!(state == 4)) { - break; - } - } - print(3); state = check(); - while(1) { - print(1); state = check(); +} +while(1) { + print(4); state = check(); + if (!(state == 4)) { + break; } } +print(3); state = check(); +while(1) { + print(1); state = check(); +} diff --git a/src/relooper/test_fuzz6.txt b/src/relooper/test_fuzz6.txt index af188ab15c652..bd45e8fdbbbd5 100644 --- a/src/relooper/test_fuzz6.txt +++ b/src/relooper/test_fuzz6.txt @@ -40,39 +40,14 @@ while(1) { print(16); state = check();// ................................................................................................................................................................................................................................................................................................................................................................ print(57); state = check();// ........................................................................................................................................................................................................................................................................................................................... print(39); state = check();// ................ - if (state % 3 == 0) { - label = 73; - } else if (state % 3 == 1) { + if (state % 3 == 1) { label = 74; - } else { + } else if (!(state % 3 == 0)) { label = 32; break; } while(1) { - if (label == 73) { - label = 0; - print(72); state = check();// .......................................................................................................... - if (state % 2 == 0) { - label = 92; - break L20; - } - print(80); state = check();// .................................... - if (state % 2 == 0) { - continue L18; - } - print(50); state = check();// ........................................ - print(29); state = check();// ............... - print(8); state = check();// .................................................................................................................................................................................................................................................... - if (state % 2 == 0) { - continue L10; - } - print(19); state = check();// ...................................................................................................................................................................................................................... - print(56); state = check();// .................................................................................................................................................................................................................... - print(34); state = check();// .......................................................................................................................................... - label = 74; - continue; - } - else if (label == 74) { + if (label == 74) { label = 0; print(73); state = check();// . if (state % 3 == 1) { @@ -87,9 +62,27 @@ while(1) { print(77); state = check();// ........................................................................................................................................................................................................................................................................................... print(76); state = check();// .............................................................................................................................................................................................................................................................................................................................................................................................................................. print(22); state = check();// ......................................................................................................... - label = 73; - continue; } + print(72); state = check();// .......................................................................................................... + if (state % 2 == 0) { + label = 92; + break L20; + } + print(80); state = check();// .................................... + if (state % 2 == 0) { + continue L18; + } + print(50); state = check();// ........................................ + print(29); state = check();// ............... + print(8); state = check();// .................................................................................................................................................................................................................................................... + if (state % 2 == 0) { + continue L10; + } + print(19); state = check();// ...................................................................................................................................................................................................................... + print(56); state = check();// .................................................................................................................................................................................................................... + print(34); state = check();// .......................................................................................................................................... + label = 74; + continue; } print(62); state = check();// ....................................................................................... } diff --git a/src/relooper/test_inf.txt b/src/relooper/test_inf.txt index 2edfc7604c3c0..379d20836d9a8 100644 --- a/src/relooper/test_inf.txt +++ b/src/relooper/test_inf.txt @@ -361,32 +361,31 @@ if (uint(i4) >= uint(i5)) { code 171 if (i2 == 0) { code 183 -} else { - code 172 - while(1) { - code 173 - if (uint(i5) >= uint(i6)) { - code 175 - } else { - code 174 - } - code 176 - if (uint(i5) >= uint(i6)) { - code 178 - } else { - code 177 - } - code 179 - if (uint(i4) >= uint(i5)) { - code 181 - } else { - code 180 - } - code 182 - if (!(i2 != 0)) { - break; - } +} +code 172 +while(1) { + code 173 + if (uint(i5) >= uint(i6)) { + code 175 + } else { + code 174 + } + code 176 + if (uint(i5) >= uint(i6)) { + code 178 + } else { + code 177 + } + code 179 + if (uint(i4) >= uint(i5)) { + code 181 + } else { + code 180 + } + code 182 + if (!(i2 != 0)) { + break; } - code 183 } +code 183 From 1bc86fdeb8bd7a8cb73e076276b36ff5d5a9e497 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sun, 11 Nov 2012 12:26:16 -0800 Subject: [PATCH 6/6] alter version to bootstrap relooper --- tools/shared.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/shared.py b/tools/shared.py index b5fd671fec1c4..b8242db30ef85 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -109,7 +109,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.0.1' +EMSCRIPTEN_VERSION = '1.0.1a' def check_sanity(force=False): try: