Bug 1204675: IonMonkey - Replace input with constant in a tableswitch, r=jandem
authorHannes Verschore <hv1989@gmail.com>
Fri, 18 Sep 2015 17:27:05 +0200
changeset 295881 ef74a17b0963c6d1fc21e888b68bc67d9196ef7a
parent 295880 045b1309490f8d1de44768effd16fe7b997ba19d
child 295882 ff69597b1ee495f1290a9a338679d8b5edf0873b
push id5245
push userraliiev@mozilla.com
push dateThu, 29 Oct 2015 11:30:51 +0000
treeherdermozilla-beta@dac831dc1bd0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjandem
bugs1204675
milestone43.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1204675: IonMonkey - Replace input with constant in a tableswitch, r=jandem
js/src/jit/IonBuilder.cpp
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -2711,16 +2711,31 @@ IonBuilder::processNextTableSwitchCase(C
 
     // Add current block as predecessor if available.
     // This means the previous case didn't have a break statement.
     // So flow will continue in this block.
     if (current) {
         current->end(MGoto::New(alloc(), successor));
         if (!successor->addPredecessor(alloc(), current))
             return ControlStatus_Error;
+    } else {
+        // If this is an actual case statement, optimize by replacing the
+        // input to the switch case with the actual number of the case.
+        // This constant has been emitted when creating the case blocks.
+        if (state.tableswitch.ins->getDefault() != successor) {
+            MConstant* constant = successor->begin()->toConstant();
+            for (uint32_t j = 0; j < successor->stackDepth(); j++) {
+                MDefinition* ins = successor->getSlot(j);
+                if (ins != state.tableswitch.ins->getOperand(0))
+                    continue;
+
+                constant->setDependency(state.tableswitch.ins);
+                successor->setSlot(j, constant);
+            }
+        }
     }
 
     // Insert successor after the current block, to maintain RPO.
     graph().moveBlockToEnd(successor);
 
     // If this is the last successor the block should stop at the end of the tableswitch
     // Else it should stop at the start of the next successor
     if (state.tableswitch.currentBlock+1 < state.tableswitch.ins->numBlocks())
@@ -3362,20 +3377,26 @@ IonBuilder::tableSwitch(JSOp op, jssrcno
             caseblock->end(MGoto::New(alloc(), defaultcase));
             if (!defaultcase->addPredecessor(alloc(), caseblock))
                 return ControlStatus_Error;
         }
 
         tableswitch->addCase(tableswitch->addSuccessor(caseblock));
 
         // If this is an actual case (not filled gap),
-        // add this block to the list that still needs to get processed
-        if (casepc != pc)
+        // add this block to the list that still needs to get processed.
+        if (casepc != pc) {
             tableswitch->addBlock(caseblock);
 
+            // Add constant to indicate which case this is for use by
+            // processNextTableSwitchCase.
+            MConstant* constant = MConstant::New(alloc(), Int32Value(i + low));
+            caseblock->add(constant);
+        }
+
         pc2 += JUMP_OFFSET_LEN;
     }
 
     // Move defaultcase to the end, to maintain RPO.
     graph().moveBlockToEnd(defaultcase);
 
     MOZ_ASSERT(tableswitch->numCases() == (uint32_t)(high - low + 1));
     MOZ_ASSERT(tableswitch->numSuccessors() > 0);