Forráskód Böngészése

[MERGE #685] X64 JIT: bad code with ToVar and register spills

Merge pull request #685 from pleath:mov_trunc
Use MOV_TRUNC in place of MOV when generating ToVar from i32 on x64. We rely on the register move to clear the upper 32 bits, so make sure it doesn't get folded into a 32-bit spill.
Paul Leathers 10 éve
szülő
commit
53e4130d69

+ 4 - 3
lib/Backend/amd64/LowererMDArch.cpp

@@ -2211,7 +2211,7 @@ LowererMDArch::EmitLoadVar(IR::Instr *instrLoad, bool isFromUint32, bool isHelpe
 void
 LowererMDArch::EmitLoadVar(IR::Instr *instrLoad, bool isFromUint32, bool isHelper)
 {
-    //    MOV e1, e_src1
+    //    MOV_TRUNC e1, e_src1
     //    CMP e1, 0             [uint32]
     //    JLT $Helper           [uint32]  -- overflows?
     //    BTS r1, VarTag_Shift
@@ -2247,10 +2247,11 @@ LowererMDArch::EmitLoadVar(IR::Instr *instrLoad, bool isFromUint32, bool isHelpe
 
     IR::RegOpnd *r1 = IR::RegOpnd::New(TyVar, m_func);
 
-    // e1 = MOV e_src1
+    // e1 = MOV_TRUNC e_src1
+    // (Use MOV_TRUNC here as we rely on the register copy to clear the upper 32 bits.)
     IR::RegOpnd *e1 = r1->Copy(m_func)->AsRegOpnd();
     e1->SetType(TyInt32);
-    instrLoad->InsertBefore(IR::Instr::New(Js::OpCode::MOV,
+    instrLoad->InsertBefore(IR::Instr::New(Js::OpCode::MOV_TRUNC,
         e1,
         src1,
         m_func));

+ 46 - 0
test/Optimizer/ToVari32_x64.js

@@ -0,0 +1,46 @@
+//-------------------------------------------------------------------------------------------------------
+// Copyright (C) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
+//-------------------------------------------------------------------------------------------------------
+
+var shouldBailout = false;
+function test0() {
+    var loopInvariant = shouldBailout ? 12 : 8;
+    var GiantPrintArray = [];
+    var protoObj0 = {};
+    var obj1 = {};
+    var protoObj1 = {};
+    var func4 = function () {
+    };
+    for (var __loopvar0 = loopInvariant; __loopvar0 != loopInvariant + 4; loopInvariant) {
+        var __loopvar1 = loopInvariant;
+        for (var __loopSecondaryVar1_0 = loopInvariant; ; loopInvariant) {
+            while (obj1.prop0) {
+                var __loopvar3 = loopInvariant;
+                do {
+                    var v0 = protoObj1[{}];
+                    protoObj1 = protoObj0;
+                    var uniqobj1 = [obj1];
+                    GiantPrintArray.push(__loopvar0);
+                    func4();
+                    if (__loopvar3 > loopInvariant + 6) {
+                    }
+                    __loopvar3 += 2;
+                } while (protoObj0);
+                GiantPrintArray('arrObj0.prop0 = ' + arrObj0);
+                GiantPrintArray('protoObj1.prop0 = ' + protoObj0);
+            }
+            if (__loopvar1 === loopInvariant) {
+                break;
+            }
+            __loopvar1++;
+        }
+        __loopvar0++;
+    }
+}
+test0();
+test0();
+test0();
+test0();
+
+WScript.Echo('pass');

+ 6 - 0
test/Optimizer/rlexe.xml

@@ -1321,4 +1321,10 @@
       <baseline>trycatch_assert.baseline</baseline>
     </default>
   </test>
+  <test>
+    <default>
+      <files>ToVarI32_x64.js</files>
+      <compile-flags>-force:rejit -off:ArrayCheckHoist -off:aggressiveinttypespec -off:bailonnoprofile -off:nativearray</compile-flags>
+    </default>
+  </test>
 </regress-exe>