20std::pair<uint32_t, uint32_t> uint64_to_high_low(uint64_t value) {
21 return {
static_cast<uint32_t
>(value >> 32),
static_cast<uint32_t
>(value)};
28 DCHECK(!other.IsInvalid());
30 if (
kind_ != other.kind_)
return false;
37 return AsWord32().Equals(other.AsWord32());
39 return AsWord64().Equals(other.AsWord64());
41 return AsFloat32().Equals(other.AsFloat32());
43 return AsFloat64().Equals(other.AsFloat64());
45 return AsTuple().Equals(other.AsTuple());
53 DCHECK(!other.IsInvalid());
55 if (other.IsAny() ||
IsNone())
return true;
56 if (
kind_ != other.kind_)
return false;
63 return AsWord32().IsSubtypeOf(other.AsWord32());
65 return AsWord64().IsSubtypeOf(other.AsWord64());
67 return AsFloat32().IsSubtypeOf(other.AsFloat32());
69 return AsFloat64().IsSubtypeOf(other.AsFloat64());
71 return AsTuple().IsSubtypeOf(other.AsTuple());
120 if (lhs.
IsNone())
return rhs;
121 if (rhs.
IsNone())
return lhs;
127 switch (lhs.
kind()) {
150 return parser.
Parse();
161 return AsWord32().AllocateOnHeap(factory);
163 return AsWord64().AllocateOnHeap(factory);
165 return AsFloat32().AllocateOnHeap(factory);
167 return AsFloat64().AllocateOnHeap(factory);
175template <
size_t Bits>
177 switch (sub_kind()) {
178 case SubKind::kRange: {
179 if (is_wrapping())
return range_to() >= value || range_from() <=
value;
180 return range_from() <= value && value <= range_to();
182 case SubKind::kSet: {
183 for (
int i = 0;
i < set_size(); ++
i) {
184 if (set_element(
i) == value)
return true;
191template <
size_t Bits>
193 if (sub_kind() != other.sub_kind())
return false;
194 switch (sub_kind()) {
195 case SubKind::kRange:
196 return (range_from() == other.range_from() &&
197 range_to() == other.range_to()) ||
198 (is_any() && other.is_any());
199 case SubKind::kSet: {
200 if (set_size() != other.set_size())
return false;
201 for (
int i = 0;
i < set_size(); ++
i) {
202 if (set_element(
i) != other.set_element(
i))
return false;
209template <
size_t Bits>
211 if (other.is_any())
return true;
212 switch (sub_kind()) {
213 case SubKind::kRange: {
214 if (other.is_set())
return false;
216 if (is_wrapping() == other.is_wrapping()) {
217 return range_from() >= other.range_from() &&
218 range_to() <= other.range_to();
220 return !is_wrapping() && (range_to() <= other.range_to() ||
221 range_from() >= other.range_from());
223 case SubKind::kSet: {
224 if (other.is_set() && set_size() > other.set_size())
return false;
225 for (
int i = 0;
i < set_size(); ++
i) {
226 if (!other.Contains(set_element(
i)))
return false;
233template <size_t Bits, typename word_t = typename WordType<Bits>::word_t>
237 const bool lhs_wrapping = l_to < l_from;
238 const bool rhs_wrapping = r_to < r_from;
243 if (!lhs_wrapping && !rhs_wrapping) {
251 if (lhs_wrapping && rhs_wrapping) {
252 const auto from = std::min(l_from, r_from);
253 const auto to = std::max(l_to, r_to);
268 if (r_from <= l_to) {
275 }
else if (r_to >= l_from) {
276 if (r_from >= l_from)
283 const auto df = r_from - l_to;
284 const auto dt = l_from - r_to;
293template <
size_t Bits>
326 auto it = std::unique(result_elements.
begin(), result_elements.
end());
327 result_elements.
pop_back(std::distance(it, result_elements.
end()));
328 if (result_elements.
size() <= kMaxSetSize) {
329 return Set(result_elements, zone);
333 return Range(result_elements.
front(), result_elements.
back(), zone);
334 }
else if (rhs.
is_set()) {
335 return LeastUpperBound(rhs, lhs, zone);
343template <
size_t Bits>
347 if (lhs.
is_any())
return rhs;
348 if (rhs.
is_any())
return lhs;
351 const auto&
x = lhs.
is_set() ? lhs : rhs;
352 const auto&
y = lhs.
is_set() ? rhs : lhs;
354 for (
int i = 0;
i <
x.set_size(); ++
i) {
355 const word_t element =
x.set_element(
i);
356 if (
y.Contains(element)) result_elements.
push_back(element);
360 return Set(result_elements, zone);
368 return result_to < result_from
381 const auto&
x = lhs_wrapping ? lhs : rhs;
382 const auto&
y = lhs_wrapping ? rhs : lhs;
385 auto subrange_low = Intersect(
y,
Range(0,
x.range_to(), zone),
386 ResolutionMode::kPreciseOrInvalid, zone);
387 DCHECK(!subrange_low.IsInvalid());
388 auto subrange_high = Intersect(
389 y,
Range(
x.range_from(), std::numeric_limits<word_t>::max(), zone),
390 ResolutionMode::kPreciseOrInvalid, zone);
391 DCHECK(!subrange_high.IsInvalid());
393 if (subrange_low.IsNone())
return subrange_high;
394 if (subrange_high.IsNone())
return subrange_low;
395 auto s_l = subrange_low.template AsWord<Bits>();
396 auto s_h = subrange_high.template AsWord<Bits>();
398 switch (resolution_mode) {
399 case ResolutionMode::kPreciseOrInvalid:
401 case ResolutionMode::kOverApproximate:
402 return LeastUpperBound(s_l, s_h, zone);
403 case ResolutionMode::kGreatestLowerBound:
404 return (s_l.unsigned_max() - s_l.unsigned_min() <
405 s_h.unsigned_max() - s_h.unsigned_min())
411template <
size_t Bits>
413 stream << (Bits == 32 ?
"Word32" :
"Word64");
414 switch (sub_kind()) {
415 case SubKind::kRange:
416 stream <<
"[0x" << std::hex << range_from() <<
", 0x" << range_to()
420 stream <<
"{" << std::hex;
421 for (
int i = 0;
i < set_size(); ++
i) {
422 stream << (
i == 0 ?
"0x" :
", 0x");
423 stream << set_element(
i);
425 stream << std::dec <<
"}";
430template <
size_t Bits>
432 if constexpr (Bits == 32) {
434 return factory->NewTurboshaftWord32RangeType(range_from(), range_to(),
438 auto result = factory->NewTurboshaftWord32SetType(set_size(),
440 for (
int i = 0;
i < set_size(); ++
i) {
441 result->set_elements(
i, set_element(
i));
447 const auto [from_high, from_low] = uint64_to_high_low(range_from());
448 const auto [to_high, to_low] = uint64_to_high_low(range_to());
449 return factory->NewTurboshaftWord64RangeType(
453 auto result = factory->NewTurboshaftWord64SetType(set_size(),
455 for (
int i = 0;
i < set_size(); ++
i) {
456 const auto [high, low] = uint64_to_high_low(set_element(
i));
457 result->set_elements_high(
i, high);
458 result->set_elements_low(
i, low);
465template <
size_t Bits>
468 if (std::isnan(value))
return has_nan();
469 switch (sub_kind()) {
470 case SubKind::kOnlySpecialValues:
472 case SubKind::kRange: {
473 return range_min() <= value && value <= range_max();
475 case SubKind::kSet: {
476 for (
int i = 0;
i < set_size(); ++
i) {
477 if (set_element(
i) == value)
return true;
484template <
size_t Bits>
486 if (sub_kind() != other.sub_kind())
return false;
487 if (special_values() != other.special_values())
return false;
488 switch (sub_kind()) {
489 case SubKind::kOnlySpecialValues:
491 case SubKind::kRange: {
492 return range() == other.range();
494 case SubKind::kSet: {
495 if (set_size() != other.set_size()) {
498 for (
int i = 0;
i < set_size(); ++
i) {
499 if (set_element(
i) != other.set_element(
i))
return false;
506template <
size_t Bits>
508 if (special_values() & ~other.special_values())
return false;
509 switch (sub_kind()) {
510 case SubKind::kOnlySpecialValues:
512 case SubKind::kRange:
513 if (!other.is_range()) {
518 return other.range_min() <= range_min() &&
519 range_max() <= other.range_max();
520 case SubKind::kSet: {
521 switch (other.sub_kind()) {
522 case SubKind::kOnlySpecialValues:
524 case SubKind::kRange:
525 return other.range_min() <= min() && max() <= other.range_max();
527 for (
int i = 0;
i < set_size(); ++
i) {
528 if (!other.Contains(set_element(
i)))
return false;
536template <
size_t Bits>
543 return Any(special_values);
549 if (lhs_finite && rhs_finite) {
553 if (result_elements.
empty()) {
554 return OnlySpecialValues(special_values);
557 auto it = std::unique(result_elements.
begin(), result_elements.
end());
558 result_elements.
pop_back(std::distance(it, result_elements.
end()));
559 if (result_elements.
size() <= kMaxSetSize) {
560 return Set(result_elements, special_values, zone);
563 special_values, zone);
565 return ReplacedSpecialValues(rhs, special_values).template AsFloat<Bits>();
567 return ReplacedSpecialValues(lhs, special_values).template AsFloat<Bits>();
573 return Range(result_min, result_max, special_values, zone);
576template <
size_t Bits>
581 if (lhs.
is_any())
return ReplacedSpecialValues(rhs, special_values);
582 if (rhs.
is_any())
return ReplacedSpecialValues(lhs, special_values);
584 return special_values ? OnlySpecialValues(special_values) :
Type::None();
588 const auto&
x = lhs.
is_set() ? lhs : rhs;
589 const auto&
y = lhs.
is_set() ? rhs : lhs;
591 for (
int i = 0;
i <
x.set_size(); ++
i) {
592 const float_t element =
x.set_element(
i);
593 if (
y.Contains(element)) result_elements.
push_back(element);
595 if (result_elements.
empty()) {
596 return special_values ? OnlySpecialValues(special_values) :
Type::None();
598 return Set(result_elements, special_values, zone);
604 if (result_min < result_max) {
605 return Range(result_min, result_max, special_values, zone);
606 }
else if (result_min == result_max) {
607 return Set({result_min}, special_values, zone);
609 return special_values ? OnlySpecialValues(special_values) :
Type::None();
612template <
size_t Bits>
614 auto PrintSpecials = [
this](
auto& stream) {
616 stream <<
"NaN" << (has_minus_zero() ?
"|MinusZero" :
"");
619 stream <<
"MinusZero";
622 stream << (Bits == 32 ?
"Float32" :
"Float64");
623 switch (sub_kind()) {
624 case SubKind::kOnlySpecialValues:
625 PrintSpecials(stream);
627 case SubKind::kRange:
628 stream <<
"[" << range_min() <<
", " << range_max() <<
"]";
629 if (has_special_values()) {
631 PrintSpecials(stream);
636 for (
int i = 0;
i < set_size(); ++
i) {
637 if (
i != 0) stream <<
", ";
638 stream << set_element(
i);
640 if (has_special_values()) {
642 PrintSpecials(stream);
650template <
size_t Bits>
652 float_t min = 0.0f, max = 0.0f;
653 constexpr uint32_t padding = 0;
654 if (is_only_special_values()) {
655 min = std::numeric_limits<float_t>::infinity();
656 max = -std::numeric_limits<float_t>::infinity();
657 return factory->NewTurboshaftFloat64RangeType(
659 }
else if (is_range()) {
660 std::tie(min, max) = minmax();
661 return factory->NewTurboshaftFloat64RangeType(
665 auto result = factory->NewTurboshaftFloat64SetType(
667 for (
int i = 0;
i < set_size(); ++
i) {
668 result->set_elements(
i, set_element(
i));
675 if (
size() != other.size())
return false;
676 for (
int i = 0;
i <
size(); ++
i) {
683 if (
size() != other.size())
return false;
684 for (
int i = 0;
i <
size(); ++
i) {
696 for (
int i = 0;
i < lhs.
size(); ++
i) {
704 for (
int i = 0;
i <
size(); ++
i) {
705 if (
i != 0) stream <<
", ";
void pop_back(size_t count=1)
T * AllocateArray(size_t length)
float_type< Bits > float_t
static Type Intersect(const FloatType &lhs, const FloatType &rhs, Zone *zone)
bool Equals(const FloatType &other) const
void PrintTo(std::ostream &stream) const
bool IsSubtypeOf(const FloatType &other) const
float_t range_or_set_max() const
base::Vector< const float_t > set_elements() const
bool Contains(float_t value) const
bool is_only_special_values() const
float_t range_or_set_min() const
static FloatType LeastUpperBound(const FloatType &lhs, const FloatType &rhs, Zone *zone)
Handle< TurboshaftType > AllocateOnHeap(Factory *factory) const
uint32_t special_values() const
static Type LeastUpperBound(const TupleType &lhs, const TupleType &rhs, Zone *zone)
bool Equals(const TupleType &other) const
bool IsSubtypeOf(const TupleType &other) const
void PrintTo(std::ostream &stream) const
const Type & element(int index) const
std::optional< Type > Parse()
static std::optional< Type > ParseFromString(const std::string_view &str, Zone *zone)
bool Equals(const Type &other) const
const TupleType & AsTuple() const
const Word32Type & AsWord32() const
void PrintTo(std::ostream &stream) const
bool IsSubtypeOf(const Type &other) const
const Float32Type & AsFloat32() const
Handle< TurboshaftType > AllocateOnHeap(Factory *factory) const
const Word64Type & AsWord64() const
const Float64Type & AsFloat64() const
static Type LeastUpperBound(const Type &lhs, const Type &rhs, Zone *zone)
Handle< TurboshaftType > AllocateOnHeap(Factory *factory) const
void PrintTo(std::ostream &stream) const
bool Equals(const WordType &other) const
static WordType LeastUpperBound(const WordType &lhs, const WordType &rhs, Zone *zone)
word_t unsigned_min() const
bool Contains(word_t value) const
bool IsSubtypeOf(const WordType &other) const
word_t set_element(int index) const
word_t range_from() const
base::Vector< const word_t > set_elements() const
static Type Intersect(const WordType &lhs, const WordType &rhs, ResolutionMode resolution_mode, Zone *zone)
static WordType Range(word_t from, word_t to, Zone *zone)
word_t unsigned_max() const
#define EXPORT_TEMPLATE_DEFINE(export)
ZoneVector< RpoNumber > & result
void vector_append(V &v, const C &container)
bool is_unique_and_sorted(const T &container)
WordType< Bits > LeastUpperBoundFromRanges(word_t l_from, word_t l_to, word_t r_from, word_t r_to, Zone *zone)
Range(V< T >, V< T >, V< T >) -> Range< T >
std::make_unsigned_t< Tagged_t > word_t
static bool IsMinusZero(double value)
#define DCHECK_NOT_NULL(val)
#define DCHECK_NE(v1, v2)
#define DCHECK(condition)
#define DCHECK_GT(v1, v2)
#define V8_EXPORT_PRIVATE