From 3f0f685829445ae82974d61f6017fdb67349c32b Mon Sep 17 00:00:00 2001
From: Dan Gohman <sunfish@mozilla.com>
Date: Fri, 9 Jan 2015 09:04:12 -0500
Subject: [PATCH] Bug 1096138 - IonMonkey: Augment Nops with Mops to avoid
 collisions with fixed live ranges. r=jandem, a=sledru

---
 js/src/jit/CodeGenerator.cpp |  6 ++++++
 js/src/jit/CodeGenerator.h   |  1 +
 js/src/jit/LIR-Common.h      |  6 ++++++
 js/src/jit/LOpcodes.h        |  1 +
 js/src/jit/Lowering.cpp      | 12 ++++++++++++
 5 files changed, 26 insertions(+)

diff --git a/js/src/jit/CodeGenerator.cpp b/js/src/jit/CodeGenerator.cpp
index 4f07524..ba14f86 100644
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -1077,6 +1077,12 @@ CodeGenerator::visitNop(LNop *lir)
 }
 
 bool
+CodeGenerator::visitMop(LMop *lir)
+{
+    return true;
+}
+
+bool
 CodeGenerator::visitOsiPoint(LOsiPoint *lir)
 {
     // Note: markOsiPoint ensures enough space exists between the last
diff --git a/js/src/jit/CodeGenerator.h b/js/src/jit/CodeGenerator.h
index 03677a5..dce095d 100644
--- a/js/src/jit/CodeGenerator.h
+++ b/js/src/jit/CodeGenerator.h
@@ -58,6 +58,7 @@ class CodeGenerator : public CodeGeneratorSpecific
 
     bool visitLabel(LLabel *lir);
     bool visitNop(LNop *lir);
+    bool visitMop(LMop *lir);
     bool visitOsiPoint(LOsiPoint *lir);
     bool visitGoto(LGoto *lir);
     bool visitTableSwitch(LTableSwitch *ins);
diff --git a/js/src/jit/LIR-Common.h b/js/src/jit/LIR-Common.h
index c90aef9..e7a0e4c 100644
--- a/js/src/jit/LIR-Common.h
+++ b/js/src/jit/LIR-Common.h
@@ -42,6 +42,12 @@ class LNop : public LInstructionHelper<0, 0, 0>
     LIR_HEADER(Nop)
 };
 
+class LMop : public LInstructionHelper<0, 0, 0>
+{
+  public:
+    LIR_HEADER(Mop)
+};
+
 // An LOsiPoint captures a snapshot after a call and ensures enough space to
 // patch in a call to the invalidation mechanism.
 //
diff --git a/js/src/jit/LOpcodes.h b/js/src/jit/LOpcodes.h
index a32d64f..cd7eef8 100644
--- a/js/src/jit/LOpcodes.h
+++ b/js/src/jit/LOpcodes.h
@@ -10,6 +10,7 @@
 #define LIR_COMMON_OPCODE_LIST(_)   \
     _(Label)                        \
     _(Nop)                          \
+    _(Mop)                          \
     _(OsiPoint)                     \
     _(MoveGroup)                    \
     _(Integer)                      \
diff --git a/js/src/jit/Lowering.cpp b/js/src/jit/Lowering.cpp
index d5f8227..48b7fa9 100644
--- a/js/src/jit/Lowering.cpp
+++ b/js/src/jit/Lowering.cpp
@@ -3616,12 +3616,24 @@ LIRGenerator::visitInstruction(MInstruction *ins)
     ins->setInWorklistUnchecked();
 #endif
 
+    // If we added a Nop for this instruction, we'll also add a Mop, so that
+    // that live-ranges for fixed register defs, which with LSRA extend through
+    // the Nop so that they can extend through the OsiPoint don't, with their
+    // one-extra extension, extend into a position where they use the input
+    // move group for the following instruction.
+    bool needsMop = !current->instructions().empty() && current->rbegin()->isNop();
+
     // If no safepoint was created, there's no need for an OSI point.
     if (LOsiPoint *osiPoint = popOsiPoint()) {
         if (!add(osiPoint))
             return false;
     }
 
+    if (needsMop) {
+        if (!add(new(alloc()) LMop))
+            return false;
+    }
+
     return true;
 }
 
-- 
2.2.1

