v8/test/mjsunit/compiler/bigint-shift-left.js
Qifan Pan 2690e2e3a3 [turbofan] Support BigInt shift operations
This CL implements Torque builtins for BigInt left shift and right
shift and truncates shift operations when the shift amount is a
constant.

- Propagate truncation if we know the operation is a left shift.
- Lower the operation to a word64 right shift if the lhs is Signed- or
  UnsignedBigInt64 and we know the op is a right shift.

A side effect of truncating left shift is it will not throw a
BigIntTooBig exception in optimized code.

Bug: v8:9407
Change-Id: Ibd42cf897ef8a35f6addd09674faf409654d6d7c
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4028142
Commit-Queue: Qifan Pan <panq@google.com>
Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
Reviewed-by: Nico Hartmann <nicohartmann@chromium.org>
Cr-Commit-Position: refs/heads/main@{#84396}
2022-11-21 14:05:07 +00:00

111 lines
3.7 KiB
JavaScript

// Copyright 2022 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 --turbofan --no-always-turbofan
(function OptimizeAndTest() {
function ShiftLeft(a, b) {
return a << b;
}
%PrepareFunctionForOptimization(ShiftLeft);
assertEquals(0n, ShiftLeft(0n, 42n));
assertEquals(-42n, ShiftLeft(-42n, 0n));
assertEquals(2n ** 42n, ShiftLeft(1n, 42n));
assertEquals(-2n, ShiftLeft(-(2n ** 512n), -511n));
assertEquals(-1n, ShiftLeft(-(2n ** 512n), -513n));
%OptimizeFunctionOnNextCall(ShiftLeft);
assertEquals(0n, ShiftLeft(0n, 42n));
assertEquals(-42n, ShiftLeft(-42n, 0n));
assertEquals(2n ** 42n, ShiftLeft(1n, 42n));
assertEquals(-2n, ShiftLeft(-(2n ** 512n), -511n));
assertEquals(-1n, ShiftLeft(-(2n ** 512n), -513n));
assertOptimized(ShiftLeft);
assertThrows(() => ShiftLeft(1n, 2n ** 30n), RangeError);
assertUnoptimized(ShiftLeft);
})();
(function OptimizeAndTest() {
function ShiftLeftByPositive(a) {
return BigInt.asIntN(62, a << 42n);
}
%PrepareFunctionForOptimization(ShiftLeftByPositive);
assertEquals(0n, ShiftLeftByPositive(0n));
%OptimizeFunctionOnNextCall(ShiftLeftByPositive);
assertEquals(0n, ShiftLeftByPositive(0n));
assertEquals(2n ** 42n, ShiftLeftByPositive(1n));
assertEquals(2n ** 42n, ShiftLeftByPositive(1n + 2n ** 62n));
assertEquals(-(2n ** 42n), ShiftLeftByPositive(-1n - 2n ** 64n));
assertOptimized(ShiftLeftByPositive);
assertThrows(() => ShiftLeftByPositive(0), TypeError);
assertUnoptimized(ShiftLeftByPositive);
})();
(function OptimizeAndTest() {
const minus42 = -42n;
function ShiftLeftByNegative(a) {
return BigInt.asIntN(62, BigInt.asUintN(64, a) << minus42);
}
%PrepareFunctionForOptimization(ShiftLeftByNegative);
assertEquals(0n, ShiftLeftByNegative(0n));
%OptimizeFunctionOnNextCall(ShiftLeftByNegative);
assertEquals(0n, ShiftLeftByNegative(42n));
assertEquals(4194303n, ShiftLeftByNegative(-42n));
assertEquals(2n ** 20n, ShiftLeftByNegative(1n + 2n ** 62n));
assertEquals(3145727n, ShiftLeftByNegative(-1n - 2n ** 62n - 2n ** 64n));
assertOptimized(ShiftLeftByNegative);
assertThrows(() => ShiftLeftByNegative(0), TypeError);
if (%Is64Bit()) {
// BigInt truncation is not inlined on 32-bit platforms so there is no
// checks for BigInt, thus deopt will not be triggered.
assertUnoptimized(ShiftLeftByNegative);
}
})();
(function OptimizeAndTest() {
function ShiftLeftBy64(a) {
return BigInt.asIntN(62, a << 64n);
}
%PrepareFunctionForOptimization(ShiftLeftBy64);
assertEquals(0n, ShiftLeftBy64(0n));
%OptimizeFunctionOnNextCall(ShiftLeftBy64);
assertEquals(0n, ShiftLeftBy64(0n));
assertEquals(0n, ShiftLeftBy64(1n));
assertEquals(0n, ShiftLeftBy64(1n + 2n ** 62n));
assertEquals(0n, ShiftLeftBy64(-1n - 2n ** 64n));
assertOptimized(ShiftLeftBy64);
assertThrows(() => ShiftLeftBy64(0), TypeError);
assertUnoptimized(ShiftLeftBy64);
})();
(function OptimizeAndTest() {
const bi = 2n ** 64n;
function ShiftLeftByLarge(a) {
return BigInt.asIntN(62, a << bi);
}
%PrepareFunctionForOptimization(ShiftLeftByLarge);
assertEquals(0n, ShiftLeftByLarge(0n));
%OptimizeFunctionOnNextCall(ShiftLeftByLarge);
assertEquals(0n, ShiftLeftByLarge(0n));
if (%Is64Bit()) {
// After optimization, a truncated left shift will not throw a
// BigIntTooBig exception just as truncated addition.
assertEquals(0n, ShiftLeftByLarge(1n));
assertEquals(0n, ShiftLeftByLarge(1n + 2n ** 62n));
assertEquals(0n, ShiftLeftByLarge(-1n - 2n ** 64n));
}
assertOptimized(ShiftLeftByLarge);
assertThrows(() => ShiftLeftByLarge(0), TypeError);
assertUnoptimized(ShiftLeftByLarge);
})();