diff --git a/src/compiler/turboshaft/type-inference-reducer.h b/src/compiler/turboshaft/type-inference-reducer.h index 4e08b49169..17fa032a00 100644 --- a/src/compiler/turboshaft/type-inference-reducer.h +++ b/src/compiler/turboshaft/type-inference-reducer.h @@ -679,7 +679,18 @@ struct FloatOperationTyper { } 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(); // a ** b produces NaN if a < 0 && b is fraction. diff --git a/src/compiler/turboshaft/types.h b/src/compiler/turboshaft/types.h index 44576eab43..494a49194e 100644 --- a/src/compiler/turboshaft/types.h +++ b/src/compiler/turboshaft/types.h @@ -395,6 +395,10 @@ class EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE) WordType : public Type { DCHECK_EQ(set_size(), 1); 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 { switch (sub_kind()) { case SubKind::kRange: @@ -637,6 +641,12 @@ class EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE) FloatType : public Type { DCHECK_EQ(set_size(), 1); 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 bool Contains(float_t value) const; diff --git a/test/mjsunit/regress/regress-1412629.js b/test/mjsunit/regress/regress-1412629.js new file mode 100644 index 0000000000..03e67d12fd --- /dev/null +++ b/test/mjsunit/regress/regress-1412629.js @@ -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));