diff --git a/lib/Backend/GlobOptBailOut.cpp b/lib/Backend/GlobOptBailOut.cpp
index 804d9ae751b..b9c37173604 100644
--- a/lib/Backend/GlobOptBailOut.cpp
+++ b/lib/Backend/GlobOptBailOut.cpp
@@ -1085,6 +1085,43 @@ GlobOpt::ConvertToByteCodeUses(IR::Instr * instr)
this->CaptureByteCodeSymUses(instr);
IR::ByteCodeUsesInstr * byteCodeUsesInstr = this->InsertByteCodeUses(instr, true);
instr->Remove();
+ // If possible, we want to aggregate with subsequent ByteCodeUses Instructions, so
+ // that we can do some optimizations in other places where we can simplify args in
+ // a compare, but still need to generate them for bailouts. Without this, we cause
+ // problems because we end up with an instruction losing atomicity in terms of its
+ // bytecode use and generation lifetimes.
+ if (byteCodeUsesInstr &&
+ byteCodeUsesInstr->m_next &&
+ byteCodeUsesInstr->m_next->m_opcode == Js::OpCode::ByteCodeUses &&
+ byteCodeUsesInstr->GetByteCodeOffset() == byteCodeUsesInstr->m_next->GetByteCodeOffset()
+ )
+ {
+ IR::ByteCodeUsesInstr * nextinstr = byteCodeUsesInstr->m_next->AsByteCodeUsesInstr();
+ if (nextinstr->GetDst() == nullptr)
+ {
+ // We move all of the uses of the next bytecodeuses instruction into this one. The
+ // instruction is notably not removed or repurposed; unfortunately, at this point,
+ // doing either would be somewhat complex. Removing the instruction breaks some of
+ // the assumptions made in other code (notably RemoveCodeAfterNoFallthroughInstr),
+ // and repurposing it by removing the newly-added byteCodeUsesInstr requires us to
+ // be able to handle transferring the Dst reg in a couple more cases (like if it's
+ // single-def).
+ if (nextinstr->byteCodeUpwardExposedUsed)
+ {
+ if (byteCodeUsesInstr->byteCodeUpwardExposedUsed)
+ {
+ byteCodeUsesInstr->byteCodeUpwardExposedUsed->Or(nextinstr->byteCodeUpwardExposedUsed);
+ JitAdelete(nextinstr->byteCodeUpwardExposedUsed->GetAllocator(), nextinstr->byteCodeUpwardExposedUsed);
+ nextinstr->byteCodeUpwardExposedUsed = nullptr;
+ }
+ else
+ {
+ byteCodeUsesInstr->byteCodeUpwardExposedUsed = nextinstr->byteCodeUpwardExposedUsed;
+ nextinstr->byteCodeUpwardExposedUsed = nullptr;
+ }
+ }
+ }
+ }
return byteCodeUsesInstr;
}
diff --git a/test/Bugs/bug9080773_2.js b/test/Bugs/bug9080773_2.js
new file mode 100644
index 00000000000..5cad9d61436
--- /dev/null
+++ b/test/Bugs/bug9080773_2.js
@@ -0,0 +1,15 @@
+//-------------------------------------------------------------------------------------------------------
+// Copyright (C) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
+//-------------------------------------------------------------------------------------------------------
+function test0() {
+ var protoObj1 = {};
+ for (var __loopSecondaryVar1000_0 = 10; protoObj1.length; protoObj1) {
+ var v4 = prop0 >>> 0 < 0;
+ }
+}
+test0();
+test0();
+test0();
+
+WScript.Echo("PASSED");
diff --git a/test/Bugs/rlexe.xml b/test/Bugs/rlexe.xml
index 266134bd921..f165c0cb8bb 100644
--- a/test/Bugs/rlexe.xml
+++ b/test/Bugs/rlexe.xml
@@ -290,6 +290,12 @@
-maxinterpretcount:1 -off:simplejit
+
+
+ bug9080773_2.js
+ -maxinterpretcount:1 -maxsimplejitruncount:1
+
+
b208_asmjs.js