summaryrefslogtreecommitdiffstats
path: root/js/src/jit/BranchHinting.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/jit/BranchHinting.cpp')
-rw-r--r--js/src/jit/BranchHinting.cpp61
1 files changed, 61 insertions, 0 deletions
diff --git a/js/src/jit/BranchHinting.cpp b/js/src/jit/BranchHinting.cpp
new file mode 100644
index 0000000000..01c311267f
--- /dev/null
+++ b/js/src/jit/BranchHinting.cpp
@@ -0,0 +1,61 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: set ts=8 sts=2 et sw=2 tw=80:
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "jit/BranchHinting.h"
+
+#include "jit/IonAnalysis.h"
+#include "jit/JitSpewer.h"
+#include "jit/MIRGenerator.h"
+#include "jit/MIRGraph.h"
+
+using namespace js;
+using namespace js::jit;
+
+// Implementation of the branch hinting proposal
+// Some control instructions (if and br_if) can have a hint of the form
+// Likely or unlikely. That means a specific branch will be likely/unlikely
+// to be executed at runtime.
+
+// In a first pass, we tag the basic blocks if we have a hint.
+// In a Mir to Mir transformation, we read the hints and do something with it:
+// - Unlikely blocks are pushed to the end of the function.
+// Because of Ion's structure, we don't do that for blocks inside a loop.
+// - TODO: do something for likely blocks.
+// - TODO: register allocator can be tuned depending on the hints.
+bool jit::BranchHinting(MIRGenerator* mir, MIRGraph& graph) {
+ JitSpew(JitSpew_BranchHint, "Beginning BranchHinting pass");
+
+ // Move towards the end all blocks marked as unlikely
+ mozilla::Vector<MBasicBlock*, 0> toBeMoved;
+
+ for (MBasicBlock* block : graph) {
+ // If this block has a return instruction, it's safe to push it
+ // to the end of the graph.
+ // If the block doesn't contain a return, a backedge outside a loop will be
+ // created, which would break ReversePostOrder assertions.
+ // Avoid moving a block if it's in the middle of a loop as well.
+ if (block->branchHintingUnlikely() && block->loopDepth() == 0 &&
+ block->hasLastIns() && block->lastIns()->is<js::jit::MWasmReturn>()) {
+ if (!toBeMoved.append(block)) {
+ return false;
+ }
+ }
+ }
+
+ for (MBasicBlock* block : toBeMoved) {
+#ifdef JS_JITSPEW
+ JitSpew(JitSpew_BranchHint, "Moving block%u to the end", block->id());
+#endif
+ graph.moveBlockToEnd(block);
+ }
+
+ if (!toBeMoved.empty()) {
+ // Renumber blocks after moving them around.
+ RenumberBlocks(graph);
+ }
+
+ return true;
+}