[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} (cherry picked from commit 02f84c745fc0cae5927a66dc4a3e81334e8f60a6) Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2821951 Reviewed-by: Deepti Gandluri <gdeepti@chromium.org>
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()); +})();