[turboshaft] Fix typing of NaN ** 0

Bug: v8:12783, chromium:1412629
Change-Id: If00a7467443df50cd2c79b3bb09f9dd92dd0548b
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4221773
Auto-Submit: Nico Hartmann <nicohartmann@chromium.org>
Commit-Queue: Jakob Kummerow <jkummerow@chromium.org>
Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/main@{#85687}
This commit is contained in:
Nico Hartmann 2023-02-06 14:26:39 +01:00 committed by V8 LUCI CQ
parent 8a6b841721
commit 6d2bd5afdc
3 changed files with 40 additions and 1 deletions

View File

@ -679,7 +679,18 @@ struct FloatOperationTyper {
} }
static Type Power(const type_t& l, const type_t& r, Zone* zone) { static Type Power(const type_t& l, const type_t& r, Zone* zone) {
if (l.is_only_nan() || r.is_only_nan()) return type_t::NaN(); // x ** NaN => Nan.
if (r.is_only_nan()) return type_t::NaN();
// x ** +-0 => 1.
if (r.is_constant(0) || r.is_only_minus_zero()) return type_t::Constant(1);
if (l.is_only_nan()) {
// NaN ** 0 => 1.
if (r.Contains(0) || r.has_minus_zero()) {
return type_t::Set({1}, type_t::kNaN, zone);
}
// NaN ** x => NaN (x != +-0).
return type_t::NaN();
}
bool maybe_nan = l.has_nan() || r.has_nan(); bool maybe_nan = l.has_nan() || r.has_nan();
// a ** b produces NaN if a < 0 && b is fraction. // a ** b produces NaN if a < 0 && b is fraction.

View File

@ -395,6 +395,10 @@ class EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE) WordType : public Type {
DCHECK_EQ(set_size(), 1); DCHECK_EQ(set_size(), 1);
return set_element(0); return set_element(0);
} }
bool is_constant(word_t value) const {
if (auto c = try_get_constant()) return *c == value;
return false;
}
word_t unsigned_min() const { word_t unsigned_min() const {
switch (sub_kind()) { switch (sub_kind()) {
case SubKind::kRange: case SubKind::kRange:
@ -637,6 +641,12 @@ class EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE) FloatType : public Type {
DCHECK_EQ(set_size(), 1); DCHECK_EQ(set_size(), 1);
return set_element(0); return set_element(0);
} }
bool is_constant(float_t value) const {
if (V8_UNLIKELY(std::isnan(value))) return is_only_nan();
if (V8_UNLIKELY(IsMinusZero(value))) return is_only_minus_zero();
if (auto c = try_get_constant()) return *c == value;
return false;
}
// Misc // Misc
bool Contains(float_t value) const; bool Contains(float_t value) const;

View File

@ -0,0 +1,18 @@
// Copyright 2023 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 foo(x) {
return NaN ** x;
}
%PrepareFunctionForOptimization(foo);
assertEquals(NaN, foo(1));
assertEquals(1, foo(0));
assertEquals(1, foo(-0));
%OptimizeFunctionOnNextCall(foo);
assertEquals(NaN, foo(1));
assertEquals(1, foo(0));
assertEquals(1, foo(-0));