aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2013-06-01 15:07:23 -0700
committerAlon Zakai <alonzakai@gmail.com>2013-06-01 15:07:39 -0700
commit3c58fd7d832ce71579b3cb7cb4765d37d70102e2 (patch)
tree198e2b7a8dd5089a421b7dbab1ad01ecf4ae0d26
parent6cf99050e7cffd0c13dbced3e3559afd7a70f006 (diff)
improve RemoveUnneededFlows to handle flows into loops with a single entry1.4.6
-rw-r--r--src/relooper/Relooper.cpp31
-rw-r--r--src/relooper/Relooper.h1
-rw-r--r--src/relooper/test.txt9
-rw-r--r--tools/shared.py2
4 files changed, 34 insertions, 9 deletions
diff --git a/src/relooper/Relooper.cpp b/src/relooper/Relooper.cpp
index cb989e20..e91c6e74 100644
--- a/src/relooper/Relooper.cpp
+++ b/src/relooper/Relooper.cpp
@@ -893,10 +893,22 @@ void Relooper::Calculate(Block *Entry) {
func(Loop->Next); \
}
+ // Find the single block that must be hit in a shape, or NULL if there is more than one
+ Block *FollowNaturalFlow(Shape *S) {
+ SHAPE_SWITCH(S, {
+ return Simple->Inner;
+ }, {
+ return NULL;
+ }, {
+ return FollowNaturalFlow(Loop->Inner);
+ });
+ }
+
// Remove unneeded breaks and continues.
// A flow operation is trivially unneeded if the shape we naturally get to by normal code
// execution is the same as the flow forces us to.
void RemoveUnneededFlows(Shape *Root, Shape *Natural=NULL) {
+ Block *NaturalBlock = FollowNaturalFlow(Natural);
Shape *Next = Root;
while (Next) {
Root = Next;
@@ -911,7 +923,7 @@ void Relooper::Calculate(Block *Entry) {
for (BlockBranchMap::iterator iter = Simple->Inner->ProcessedBranchesOut.begin(); iter != Simple->Inner->ProcessedBranchesOut.end(); iter++) {
Block *Target = iter->first;
Branch *Details = iter->second;
- if (Details->Type != Branch::Direct && Target->Parent == Natural) {
+ if (Details->Type != Branch::Direct && Target == NaturalBlock) { // note: cannot handle split blocks
Details->Type = Branch::Direct;
if (MultipleShape *Multiple = Shape::IsMultiple(Details->Ancestor)) {
Multiple->NeedLoop--;
@@ -1026,7 +1038,7 @@ void Relooper::SetAsmJSMode(int On) {
#if DEBUG
// Debugging
-void DebugDump(BlockSet &Blocks, const char *prefix) {
+void Debugging::Dump(BlockSet &Blocks, const char *prefix) {
if (prefix) printf("%s ", prefix);
for (BlockSet::iterator iter = Blocks.begin(); iter != Blocks.end(); iter++) {
Block *Curr = *iter;
@@ -1039,6 +1051,21 @@ void DebugDump(BlockSet &Blocks, const char *prefix) {
}
}
+void Debugging::Dump(Shape *S, const char *prefix) {
+ if (prefix) printf("%s ", prefix);
+ printf(" %d ", S->Id);
+ SHAPE_SWITCH(S, {
+ printf("<< Simple with block %d\n", Simple->Inner->Id);
+ }, {
+ printf("<< Multiple\n");
+ for (BlockShapeMap::iterator iter = Multiple->InnerMap.begin(); iter != Multiple->InnerMap.end(); iter++) {
+ printf(" with entry %d\n", iter->first->Id);
+ }
+ }, {
+ printf("<< Loop\n");
+ });
+}
+
static void PrintDebug(const char *Format, ...) {
printf("// ");
va_list Args;
diff --git a/src/relooper/Relooper.h b/src/relooper/Relooper.h
index 5eabe827..34b6db08 100644
--- a/src/relooper/Relooper.h
+++ b/src/relooper/Relooper.h
@@ -211,6 +211,7 @@ typedef std::map<Block*, BlockSet> BlockBlockSetMap;
#if DEBUG
struct Debugging {
static void Dump(BlockSet &Blocks, const char *prefix=NULL);
+ static void Dump(Shape *S, const char *prefix=NULL);
};
#endif
diff --git a/src/relooper/test.txt b/src/relooper/test.txt
index 2ff70e66..84a8c905 100644
--- a/src/relooper/test.txt
+++ b/src/relooper/test.txt
@@ -129,12 +129,9 @@ do {
break;
}
} while(0);
-do {
- if (label == 33) {
- // block C;
- break;
- }
-} while(0);
+if (label == 33) {
+ // block C;
+}
while(1) {
// block E
// block F
diff --git a/tools/shared.py b/tools/shared.py
index f9d93289..645dfbe9 100644
--- a/tools/shared.py
+++ b/tools/shared.py
@@ -295,7 +295,7 @@ def check_node_version():
# we re-check sanity when the settings are changed)
# We also re-check sanity and clear the cache when the version changes
-EMSCRIPTEN_VERSION = '1.4.5'
+EMSCRIPTEN_VERSION = '1.4.6'
def generate_sanity():
return EMSCRIPTEN_VERSION + '|' + get_llvm_target()