[compiler][x64] Fix bug in InstructionSelector::ChangeInt32ToInt64
Bug: chromium:1196683
Change-Id: Ib4ea738b47b64edc81450583be4c80a41698c3d1
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2820971
Commit-Queue: Georg Neis <neis@chromium.org>
Reviewed-by: Nico Hartmann <nicohartmann@chromium.org>
Cr-Commit-Position: refs/heads/master@{#73903}
diff --git a/src/compiler/backend/x64/instruction-selector-x64.cc b/src/compiler/backend/x64/instruction-selector-x64.cc
index 39cd9b1..d17dd28 100644
--- a/src/compiler/backend/x64/instruction-selector-x64.cc
+++ b/src/compiler/backend/x64/instruction-selector-x64.cc
@@ -1376,7 +1376,9 @@
opcode = load_rep.IsSigned() ? kX64Movsxwq : kX64Movzxwq;
break;
case MachineRepresentation::kWord32:
- opcode = load_rep.IsSigned() ? kX64Movsxlq : kX64Movl;
+ // ChangeInt32ToInt64 must interpret its input as a _signed_ 32-bit
+ // integer, so here we must sign-extend the loaded value in any case.
+ opcode = kX64Movsxlq;
break;
default:
UNREACHABLE();
diff --git a/test/mjsunit/compiler/regress-1196683.js b/test/mjsunit/compiler/regress-1196683.js
new file mode 100644
index 0000000..abd7d6b
--- /dev/null
+++ b/test/mjsunit/compiler/regress-1196683.js
@@ -0,0 +1,56 @@
+// Copyright 2021 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+
+
+(function() {
+ const arr = new Uint32Array([2**31]);
+ function foo() {
+ return (arr[0] ^ 0) + 1;
+ }
+ %PrepareFunctionForOptimization(foo);
+ assertEquals(-(2**31) + 1, foo());
+ %OptimizeFunctionOnNextCall(foo);
+ assertEquals(-(2**31) + 1, foo());
+});
+
+
+// The remaining tests already passed without the bugfix.
+
+
+(function() {
+ const arr = new Uint16Array([2**15]);
+ function foo() {
+ return (arr[0] ^ 0) + 1;
+ }
+ %PrepareFunctionForOptimization(foo);
+ assertEquals(2**15 + 1, foo());
+ %OptimizeFunctionOnNextCall(foo);
+ assertEquals(2**15 + 1, foo());
+})();
+
+
+(function() {
+ const arr = new Uint8Array([2**7]);
+ function foo() {
+ return (arr[0] ^ 0) + 1;
+ }
+ %PrepareFunctionForOptimization(foo);
+ assertEquals(2**7 + 1, foo());
+ %OptimizeFunctionOnNextCall(foo);
+ assertEquals(2**7 + 1, foo());
+})();
+
+
+(function() {
+ const arr = new Int32Array([-(2**31)]);
+ function foo() {
+ return (arr[0] >>> 0) + 1;
+ }
+ %PrepareFunctionForOptimization(foo);
+ assertEquals(2**31 + 1, foo());
+ %OptimizeFunctionOnNextCall(foo);
+ assertEquals(2**31 + 1, foo());
+})();