[turbofan] Move UseInfo to its own file
Change-Id: Idbd61bf934b08c4e9afdfc7e939787f842952f65 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3948786 Auto-Submit: Nico Hartmann <nicohartmann@chromium.org> Reviewed-by: Darius Mercadier <dmercadier@chromium.org> Commit-Queue: Darius Mercadier <dmercadier@chromium.org> Cr-Commit-Position: refs/heads/main@{#83660}
This commit is contained in:
parent
bdfefe302a
commit
aa388de13d
@ -2913,6 +2913,7 @@ filegroup(
|
||||
"src/compiler/typer.h",
|
||||
"src/compiler/types.cc",
|
||||
"src/compiler/types.h",
|
||||
"src/compiler/use-info.h",
|
||||
"src/compiler/value-numbering-reducer.cc",
|
||||
"src/compiler/value-numbering-reducer.h",
|
||||
"src/compiler/verifier.cc",
|
||||
|
1
BUILD.gn
1
BUILD.gn
@ -2936,6 +2936,7 @@ v8_header_set("v8_internal_headers") {
|
||||
"src/compiler/typed-optimization.h",
|
||||
"src/compiler/typer.h",
|
||||
"src/compiler/types.h",
|
||||
"src/compiler/use-info.h",
|
||||
"src/compiler/value-numbering-reducer.h",
|
||||
"src/compiler/verifier.h",
|
||||
"src/compiler/write-barrier-kind.h",
|
||||
|
@ -43,6 +43,9 @@ bool operator!=(FeedbackSource const&, FeedbackSource const&);
|
||||
|
||||
V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
|
||||
FeedbackSource const&);
|
||||
inline size_t hash_value(const FeedbackSource& value) {
|
||||
return FeedbackSource::Hash()(value);
|
||||
}
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace internal
|
||||
|
@ -50,6 +50,25 @@ inline size_t hash_value(StackCheckKind kind) {
|
||||
return static_cast<size_t>(kind);
|
||||
}
|
||||
|
||||
enum class CheckForMinusZeroMode : uint8_t {
|
||||
kCheckForMinusZero,
|
||||
kDontCheckForMinusZero,
|
||||
};
|
||||
|
||||
inline size_t hash_value(CheckForMinusZeroMode mode) {
|
||||
return static_cast<size_t>(mode);
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, CheckForMinusZeroMode mode) {
|
||||
switch (mode) {
|
||||
case CheckForMinusZeroMode::kCheckForMinusZero:
|
||||
return os << "check-for-minus-zero";
|
||||
case CheckForMinusZeroMode::kDontCheckForMinusZero:
|
||||
return os << "dont-check-for-minus-zero";
|
||||
}
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
// The CallFeedbackRelation provides the meaning of the call feedback for a
|
||||
// TurboFan JSCall operator
|
||||
// - kReceiver: The call target was Function.prototype.apply and its receiver
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "src/compiler/feedback-source.h"
|
||||
#include "src/compiler/js-graph.h"
|
||||
#include "src/compiler/simplified-operator.h"
|
||||
#include "src/compiler/use-info.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
@ -17,312 +18,6 @@ namespace compiler {
|
||||
class SimplifiedLoweringVerifier;
|
||||
class TypeCache;
|
||||
|
||||
enum IdentifyZeros : uint8_t { kIdentifyZeros, kDistinguishZeros };
|
||||
|
||||
class Truncation final {
|
||||
public:
|
||||
// Constructors.
|
||||
static Truncation None() {
|
||||
return Truncation(TruncationKind::kNone, kIdentifyZeros);
|
||||
}
|
||||
static Truncation Bool() {
|
||||
return Truncation(TruncationKind::kBool, kIdentifyZeros);
|
||||
}
|
||||
static Truncation Word32() {
|
||||
return Truncation(TruncationKind::kWord32, kIdentifyZeros);
|
||||
}
|
||||
static Truncation Word64() {
|
||||
return Truncation(TruncationKind::kWord64, kIdentifyZeros);
|
||||
}
|
||||
static Truncation OddballAndBigIntToNumber(
|
||||
IdentifyZeros identify_zeros = kDistinguishZeros) {
|
||||
return Truncation(TruncationKind::kOddballAndBigIntToNumber,
|
||||
identify_zeros);
|
||||
}
|
||||
static Truncation Any(IdentifyZeros identify_zeros = kDistinguishZeros) {
|
||||
return Truncation(TruncationKind::kAny, identify_zeros);
|
||||
}
|
||||
|
||||
static Truncation Generalize(Truncation t1, Truncation t2) {
|
||||
return Truncation(
|
||||
Generalize(t1.kind(), t2.kind()),
|
||||
GeneralizeIdentifyZeros(t1.identify_zeros(), t2.identify_zeros()));
|
||||
}
|
||||
|
||||
// Queries.
|
||||
bool IsUnused() const { return kind_ == TruncationKind::kNone; }
|
||||
bool IsUsedAsBool() const {
|
||||
return LessGeneral(kind_, TruncationKind::kBool);
|
||||
}
|
||||
bool IsUsedAsWord32() const {
|
||||
return LessGeneral(kind_, TruncationKind::kWord32);
|
||||
}
|
||||
bool IsUsedAsWord64() const {
|
||||
return LessGeneral(kind_, TruncationKind::kWord64);
|
||||
}
|
||||
bool TruncatesOddballAndBigIntToNumber() const {
|
||||
return LessGeneral(kind_, TruncationKind::kOddballAndBigIntToNumber);
|
||||
}
|
||||
bool IdentifiesUndefinedAndZero() {
|
||||
return LessGeneral(kind_, TruncationKind::kWord32) ||
|
||||
LessGeneral(kind_, TruncationKind::kBool);
|
||||
}
|
||||
bool IdentifiesZeroAndMinusZero() const {
|
||||
return identify_zeros() == kIdentifyZeros;
|
||||
}
|
||||
|
||||
// Operators.
|
||||
bool operator==(Truncation other) const {
|
||||
return kind() == other.kind() && identify_zeros() == other.identify_zeros();
|
||||
}
|
||||
bool operator!=(Truncation other) const { return !(*this == other); }
|
||||
|
||||
// Debug utilities.
|
||||
const char* description() const;
|
||||
bool IsLessGeneralThan(Truncation other) const {
|
||||
return LessGeneral(kind(), other.kind()) &&
|
||||
LessGeneralIdentifyZeros(identify_zeros(), other.identify_zeros());
|
||||
}
|
||||
|
||||
IdentifyZeros identify_zeros() const { return identify_zeros_; }
|
||||
|
||||
private:
|
||||
enum class TruncationKind : uint8_t {
|
||||
kNone,
|
||||
kBool,
|
||||
kWord32,
|
||||
kWord64,
|
||||
kOddballAndBigIntToNumber,
|
||||
kAny
|
||||
};
|
||||
|
||||
explicit Truncation(TruncationKind kind, IdentifyZeros identify_zeros)
|
||||
: kind_(kind), identify_zeros_(identify_zeros) {}
|
||||
|
||||
TruncationKind kind() const { return kind_; }
|
||||
|
||||
friend class SimplifiedLoweringVerifier;
|
||||
TruncationKind kind_;
|
||||
IdentifyZeros identify_zeros_;
|
||||
|
||||
static TruncationKind Generalize(TruncationKind rep1, TruncationKind rep2);
|
||||
static IdentifyZeros GeneralizeIdentifyZeros(IdentifyZeros i1,
|
||||
IdentifyZeros i2);
|
||||
static bool LessGeneral(TruncationKind rep1, TruncationKind rep2);
|
||||
static bool LessGeneralIdentifyZeros(IdentifyZeros u1, IdentifyZeros u2);
|
||||
};
|
||||
|
||||
enum class TypeCheckKind : uint8_t {
|
||||
kNone,
|
||||
kSignedSmall,
|
||||
kSigned32,
|
||||
kSigned64,
|
||||
kNumber,
|
||||
kNumberOrBoolean,
|
||||
kNumberOrOddball,
|
||||
kHeapObject,
|
||||
kBigInt,
|
||||
kBigInt64,
|
||||
kArrayIndex
|
||||
};
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, TypeCheckKind type_check) {
|
||||
switch (type_check) {
|
||||
case TypeCheckKind::kNone:
|
||||
return os << "None";
|
||||
case TypeCheckKind::kSignedSmall:
|
||||
return os << "SignedSmall";
|
||||
case TypeCheckKind::kSigned32:
|
||||
return os << "Signed32";
|
||||
case TypeCheckKind::kSigned64:
|
||||
return os << "Signed64";
|
||||
case TypeCheckKind::kNumber:
|
||||
return os << "Number";
|
||||
case TypeCheckKind::kNumberOrBoolean:
|
||||
return os << "NumberOrBoolean";
|
||||
case TypeCheckKind::kNumberOrOddball:
|
||||
return os << "NumberOrOddball";
|
||||
case TypeCheckKind::kHeapObject:
|
||||
return os << "HeapObject";
|
||||
case TypeCheckKind::kBigInt:
|
||||
return os << "BigInt";
|
||||
case TypeCheckKind::kBigInt64:
|
||||
return os << "BigInt64";
|
||||
case TypeCheckKind::kArrayIndex:
|
||||
return os << "ArrayIndex";
|
||||
}
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
// The {UseInfo} class is used to describe a use of an input of a node.
|
||||
//
|
||||
// This information is used in two different ways, based on the phase:
|
||||
//
|
||||
// 1. During propagation, the use info is used to inform the input node
|
||||
// about what part of the input is used (we call this truncation) and what
|
||||
// is the preferred representation. For conversions that will require
|
||||
// checks, we also keep track of whether a minus zero check is needed.
|
||||
//
|
||||
// 2. During lowering, the use info is used to properly convert the input
|
||||
// to the preferred representation. The preferred representation might be
|
||||
// insufficient to do the conversion (e.g. word32->float64 conv), so we also
|
||||
// need the signedness information to produce the correct value.
|
||||
// Additionally, use info may contain {CheckParameters} which contains
|
||||
// information for the deoptimizer such as a CallIC on which speculation
|
||||
// should be disallowed if the check fails.
|
||||
class UseInfo {
|
||||
public:
|
||||
UseInfo(MachineRepresentation representation, Truncation truncation,
|
||||
TypeCheckKind type_check = TypeCheckKind::kNone,
|
||||
const FeedbackSource& feedback = FeedbackSource())
|
||||
: representation_(representation),
|
||||
truncation_(truncation),
|
||||
type_check_(type_check),
|
||||
feedback_(feedback) {}
|
||||
static UseInfo TruncatingWord32() {
|
||||
return UseInfo(MachineRepresentation::kWord32, Truncation::Word32());
|
||||
}
|
||||
static UseInfo CheckedBigIntTruncatingWord64(const FeedbackSource& feedback) {
|
||||
// Note that Trunction::Word64() can safely use kIdentifyZero, because
|
||||
// TypeCheckKind::kBigInt will make sure we deopt for anything other than
|
||||
// type BigInt anyway.
|
||||
return UseInfo(MachineRepresentation::kWord64, Truncation::Word64(),
|
||||
TypeCheckKind::kBigInt, feedback);
|
||||
}
|
||||
static UseInfo CheckedBigInt64AsWord64(const FeedbackSource& feedback) {
|
||||
return UseInfo(MachineRepresentation::kWord64, Truncation::Any(),
|
||||
TypeCheckKind::kBigInt64, feedback);
|
||||
}
|
||||
static UseInfo Word64() {
|
||||
return UseInfo(MachineRepresentation::kWord64, Truncation::Any());
|
||||
}
|
||||
static UseInfo Word() {
|
||||
return UseInfo(MachineType::PointerRepresentation(), Truncation::Any());
|
||||
}
|
||||
static UseInfo Bool() {
|
||||
return UseInfo(MachineRepresentation::kBit, Truncation::Bool());
|
||||
}
|
||||
static UseInfo Float32() {
|
||||
return UseInfo(MachineRepresentation::kFloat32, Truncation::Any());
|
||||
}
|
||||
static UseInfo Float64() {
|
||||
return UseInfo(MachineRepresentation::kFloat64, Truncation::Any());
|
||||
}
|
||||
static UseInfo TruncatingFloat64(
|
||||
IdentifyZeros identify_zeros = kDistinguishZeros) {
|
||||
return UseInfo(MachineRepresentation::kFloat64,
|
||||
Truncation::OddballAndBigIntToNumber(identify_zeros));
|
||||
}
|
||||
static UseInfo AnyTagged() {
|
||||
return UseInfo(MachineRepresentation::kTagged, Truncation::Any());
|
||||
}
|
||||
static UseInfo TaggedSigned() {
|
||||
return UseInfo(MachineRepresentation::kTaggedSigned, Truncation::Any());
|
||||
}
|
||||
static UseInfo TaggedPointer() {
|
||||
return UseInfo(MachineRepresentation::kTaggedPointer, Truncation::Any());
|
||||
}
|
||||
|
||||
// Possibly deoptimizing conversions.
|
||||
static UseInfo CheckedTaggedAsArrayIndex(const FeedbackSource& feedback) {
|
||||
return UseInfo(MachineType::PointerRepresentation(),
|
||||
Truncation::Any(kIdentifyZeros), TypeCheckKind::kArrayIndex,
|
||||
feedback);
|
||||
}
|
||||
static UseInfo CheckedHeapObjectAsTaggedPointer(
|
||||
const FeedbackSource& feedback) {
|
||||
return UseInfo(MachineRepresentation::kTaggedPointer, Truncation::Any(),
|
||||
TypeCheckKind::kHeapObject, feedback);
|
||||
}
|
||||
|
||||
static UseInfo CheckedBigIntAsTaggedPointer(const FeedbackSource& feedback) {
|
||||
return UseInfo(MachineRepresentation::kTaggedPointer, Truncation::Any(),
|
||||
TypeCheckKind::kBigInt, feedback);
|
||||
}
|
||||
|
||||
static UseInfo CheckedSignedSmallAsTaggedSigned(
|
||||
const FeedbackSource& feedback,
|
||||
IdentifyZeros identify_zeros = kDistinguishZeros) {
|
||||
return UseInfo(MachineRepresentation::kTaggedSigned,
|
||||
Truncation::Any(identify_zeros), TypeCheckKind::kSignedSmall,
|
||||
feedback);
|
||||
}
|
||||
static UseInfo CheckedSignedSmallAsWord32(IdentifyZeros identify_zeros,
|
||||
const FeedbackSource& feedback) {
|
||||
return UseInfo(MachineRepresentation::kWord32,
|
||||
Truncation::Any(identify_zeros), TypeCheckKind::kSignedSmall,
|
||||
feedback);
|
||||
}
|
||||
static UseInfo CheckedSigned32AsWord32(IdentifyZeros identify_zeros,
|
||||
const FeedbackSource& feedback) {
|
||||
return UseInfo(MachineRepresentation::kWord32,
|
||||
Truncation::Any(identify_zeros), TypeCheckKind::kSigned32,
|
||||
feedback);
|
||||
}
|
||||
static UseInfo CheckedSigned64AsWord64(IdentifyZeros identify_zeros,
|
||||
const FeedbackSource& feedback) {
|
||||
return UseInfo(MachineRepresentation::kWord64,
|
||||
Truncation::Any(identify_zeros), TypeCheckKind::kSigned64,
|
||||
feedback);
|
||||
}
|
||||
static UseInfo CheckedNumberAsFloat64(IdentifyZeros identify_zeros,
|
||||
const FeedbackSource& feedback) {
|
||||
return UseInfo(MachineRepresentation::kFloat64,
|
||||
Truncation::Any(identify_zeros), TypeCheckKind::kNumber,
|
||||
feedback);
|
||||
}
|
||||
static UseInfo CheckedNumberAsWord32(const FeedbackSource& feedback) {
|
||||
return UseInfo(MachineRepresentation::kWord32, Truncation::Word32(),
|
||||
TypeCheckKind::kNumber, feedback);
|
||||
}
|
||||
static UseInfo CheckedNumberOrBooleanAsFloat64(
|
||||
IdentifyZeros identify_zeros, const FeedbackSource& feedback) {
|
||||
return UseInfo(MachineRepresentation::kFloat64,
|
||||
Truncation::Any(identify_zeros),
|
||||
TypeCheckKind::kNumberOrBoolean, feedback);
|
||||
}
|
||||
static UseInfo CheckedNumberOrOddballAsFloat64(
|
||||
IdentifyZeros identify_zeros, const FeedbackSource& feedback) {
|
||||
return UseInfo(MachineRepresentation::kFloat64,
|
||||
Truncation::Any(identify_zeros),
|
||||
TypeCheckKind::kNumberOrOddball, feedback);
|
||||
}
|
||||
static UseInfo CheckedNumberOrOddballAsWord32(
|
||||
const FeedbackSource& feedback) {
|
||||
return UseInfo(MachineRepresentation::kWord32, Truncation::Word32(),
|
||||
TypeCheckKind::kNumberOrOddball, feedback);
|
||||
}
|
||||
|
||||
// Undetermined representation.
|
||||
static UseInfo Any() {
|
||||
return UseInfo(MachineRepresentation::kNone, Truncation::Any());
|
||||
}
|
||||
static UseInfo AnyTruncatingToBool() {
|
||||
return UseInfo(MachineRepresentation::kNone, Truncation::Bool());
|
||||
}
|
||||
|
||||
// Value not used.
|
||||
static UseInfo None() {
|
||||
return UseInfo(MachineRepresentation::kNone, Truncation::None());
|
||||
}
|
||||
|
||||
MachineRepresentation representation() const { return representation_; }
|
||||
Truncation truncation() const { return truncation_; }
|
||||
TypeCheckKind type_check() const { return type_check_; }
|
||||
CheckForMinusZeroMode minus_zero_check() const {
|
||||
return truncation().IdentifiesZeroAndMinusZero()
|
||||
? CheckForMinusZeroMode::kDontCheckForMinusZero
|
||||
: CheckForMinusZeroMode::kCheckForMinusZero;
|
||||
}
|
||||
const FeedbackSource& feedback() const { return feedback_; }
|
||||
|
||||
private:
|
||||
MachineRepresentation representation_;
|
||||
Truncation truncation_;
|
||||
TypeCheckKind type_check_;
|
||||
FeedbackSource feedback_;
|
||||
};
|
||||
|
||||
// Contains logic related to changing the representation of values for constants
|
||||
// and other nodes, as well as lowering Simplified->Machine operators.
|
||||
// Eagerly folds any representation changes for constants.
|
||||
|
@ -235,20 +235,6 @@ CheckForMinusZeroMode CheckMinusZeroModeOf(const Operator* op) {
|
||||
return OpParameter<CheckForMinusZeroMode>(op);
|
||||
}
|
||||
|
||||
size_t hash_value(CheckForMinusZeroMode mode) {
|
||||
return static_cast<size_t>(mode);
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, CheckForMinusZeroMode mode) {
|
||||
switch (mode) {
|
||||
case CheckForMinusZeroMode::kCheckForMinusZero:
|
||||
return os << "check-for-minus-zero";
|
||||
case CheckForMinusZeroMode::kDontCheckForMinusZero:
|
||||
return os << "dont-check-for-minus-zero";
|
||||
}
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, CheckMapsFlags flags) {
|
||||
if (flags & CheckMapsFlag::kTryMigrateInstance) {
|
||||
return os << "TryMigrateInstance";
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "src/common/globals.h"
|
||||
#include "src/compiler/common-operator.h"
|
||||
#include "src/compiler/feedback-source.h"
|
||||
#include "src/compiler/globals.h"
|
||||
#include "src/compiler/node-properties.h"
|
||||
#include "src/compiler/operator.h"
|
||||
#include "src/compiler/types.h"
|
||||
@ -371,16 +372,6 @@ size_t hash_value(const CheckTaggedInputParameters& params);
|
||||
bool operator==(CheckTaggedInputParameters const&,
|
||||
CheckTaggedInputParameters const&);
|
||||
|
||||
enum class CheckForMinusZeroMode : uint8_t {
|
||||
kCheckForMinusZero,
|
||||
kDontCheckForMinusZero,
|
||||
};
|
||||
|
||||
size_t hash_value(CheckForMinusZeroMode);
|
||||
|
||||
V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&,
|
||||
CheckForMinusZeroMode);
|
||||
|
||||
CheckForMinusZeroMode CheckMinusZeroModeOf(const Operator*)
|
||||
V8_WARN_UNUSED_RESULT;
|
||||
|
||||
|
352
src/compiler/use-info.h
Normal file
352
src/compiler/use-info.h
Normal file
@ -0,0 +1,352 @@
|
||||
// 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.
|
||||
|
||||
#ifndef V8_COMPILER_USE_INFO_H_
|
||||
#define V8_COMPILER_USE_INFO_H_
|
||||
|
||||
#include "src/base/functional.h"
|
||||
#include "src/compiler/feedback-source.h"
|
||||
#include "src/compiler/globals.h"
|
||||
|
||||
namespace v8::internal::compiler {
|
||||
|
||||
enum IdentifyZeros : uint8_t { kIdentifyZeros, kDistinguishZeros };
|
||||
|
||||
class Truncation;
|
||||
size_t hash_value(const Truncation&);
|
||||
|
||||
class Truncation final {
|
||||
public:
|
||||
// Constructors.
|
||||
static Truncation None() {
|
||||
return Truncation(TruncationKind::kNone, kIdentifyZeros);
|
||||
}
|
||||
static Truncation Bool() {
|
||||
return Truncation(TruncationKind::kBool, kIdentifyZeros);
|
||||
}
|
||||
static Truncation Word32() {
|
||||
return Truncation(TruncationKind::kWord32, kIdentifyZeros);
|
||||
}
|
||||
static Truncation Word64() {
|
||||
return Truncation(TruncationKind::kWord64, kIdentifyZeros);
|
||||
}
|
||||
static Truncation OddballAndBigIntToNumber(
|
||||
IdentifyZeros identify_zeros = kDistinguishZeros) {
|
||||
return Truncation(TruncationKind::kOddballAndBigIntToNumber,
|
||||
identify_zeros);
|
||||
}
|
||||
static Truncation Any(IdentifyZeros identify_zeros = kDistinguishZeros) {
|
||||
return Truncation(TruncationKind::kAny, identify_zeros);
|
||||
}
|
||||
|
||||
static Truncation Generalize(Truncation t1, Truncation t2) {
|
||||
return Truncation(
|
||||
Generalize(t1.kind(), t2.kind()),
|
||||
GeneralizeIdentifyZeros(t1.identify_zeros(), t2.identify_zeros()));
|
||||
}
|
||||
|
||||
// Queries.
|
||||
bool IsUnused() const { return kind_ == TruncationKind::kNone; }
|
||||
bool IsUsedAsBool() const {
|
||||
return LessGeneral(kind_, TruncationKind::kBool);
|
||||
}
|
||||
bool IsUsedAsWord32() const {
|
||||
return LessGeneral(kind_, TruncationKind::kWord32);
|
||||
}
|
||||
bool IsUsedAsWord64() const {
|
||||
return LessGeneral(kind_, TruncationKind::kWord64);
|
||||
}
|
||||
bool TruncatesOddballAndBigIntToNumber() const {
|
||||
return LessGeneral(kind_, TruncationKind::kOddballAndBigIntToNumber);
|
||||
}
|
||||
bool IdentifiesUndefinedAndZero() {
|
||||
return LessGeneral(kind_, TruncationKind::kWord32) ||
|
||||
LessGeneral(kind_, TruncationKind::kBool);
|
||||
}
|
||||
bool IdentifiesZeroAndMinusZero() const {
|
||||
return identify_zeros() == kIdentifyZeros;
|
||||
}
|
||||
|
||||
// Operators.
|
||||
bool operator==(Truncation other) const {
|
||||
return kind() == other.kind() && identify_zeros() == other.identify_zeros();
|
||||
}
|
||||
bool operator!=(Truncation other) const { return !(*this == other); }
|
||||
|
||||
// Debug utilities.
|
||||
const char* description() const;
|
||||
bool IsLessGeneralThan(Truncation other) const {
|
||||
return LessGeneral(kind(), other.kind()) &&
|
||||
LessGeneralIdentifyZeros(identify_zeros(), other.identify_zeros());
|
||||
}
|
||||
|
||||
IdentifyZeros identify_zeros() const { return identify_zeros_; }
|
||||
|
||||
private:
|
||||
enum class TruncationKind : uint8_t {
|
||||
kNone,
|
||||
kBool,
|
||||
kWord32,
|
||||
kWord64,
|
||||
kOddballAndBigIntToNumber,
|
||||
kAny
|
||||
};
|
||||
|
||||
explicit Truncation(TruncationKind kind, IdentifyZeros identify_zeros)
|
||||
: kind_(kind), identify_zeros_(identify_zeros) {}
|
||||
|
||||
TruncationKind kind() const { return kind_; }
|
||||
|
||||
friend class SimplifiedLoweringVerifier;
|
||||
friend size_t hash_value(const Truncation&);
|
||||
TruncationKind kind_;
|
||||
IdentifyZeros identify_zeros_;
|
||||
|
||||
static TruncationKind Generalize(TruncationKind rep1, TruncationKind rep2);
|
||||
static IdentifyZeros GeneralizeIdentifyZeros(IdentifyZeros i1,
|
||||
IdentifyZeros i2);
|
||||
static bool LessGeneral(TruncationKind rep1, TruncationKind rep2);
|
||||
static bool LessGeneralIdentifyZeros(IdentifyZeros u1, IdentifyZeros u2);
|
||||
};
|
||||
|
||||
inline size_t hash_value(const Truncation& truncation) {
|
||||
return base::hash_combine(truncation.kind(), truncation.identify_zeros());
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os,
|
||||
const Truncation& truncation) {
|
||||
return os << truncation.description();
|
||||
}
|
||||
|
||||
enum class TypeCheckKind : uint8_t {
|
||||
kNone,
|
||||
kSignedSmall,
|
||||
kSigned32,
|
||||
kSigned64,
|
||||
kNumber,
|
||||
kNumberOrBoolean,
|
||||
kNumberOrOddball,
|
||||
kHeapObject,
|
||||
kBigInt,
|
||||
kBigInt64,
|
||||
kArrayIndex
|
||||
};
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, TypeCheckKind type_check) {
|
||||
switch (type_check) {
|
||||
case TypeCheckKind::kNone:
|
||||
return os << "None";
|
||||
case TypeCheckKind::kSignedSmall:
|
||||
return os << "SignedSmall";
|
||||
case TypeCheckKind::kSigned32:
|
||||
return os << "Signed32";
|
||||
case TypeCheckKind::kSigned64:
|
||||
return os << "Signed64";
|
||||
case TypeCheckKind::kNumber:
|
||||
return os << "Number";
|
||||
case TypeCheckKind::kNumberOrBoolean:
|
||||
return os << "NumberOrBoolean";
|
||||
case TypeCheckKind::kNumberOrOddball:
|
||||
return os << "NumberOrOddball";
|
||||
case TypeCheckKind::kHeapObject:
|
||||
return os << "HeapObject";
|
||||
case TypeCheckKind::kBigInt:
|
||||
return os << "BigInt";
|
||||
case TypeCheckKind::kBigInt64:
|
||||
return os << "BigInt64";
|
||||
case TypeCheckKind::kArrayIndex:
|
||||
return os << "ArrayIndex";
|
||||
}
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
// The {UseInfo} class is used to describe a use of an input of a node.
|
||||
//
|
||||
// This information is used in two different ways, based on the phase:
|
||||
//
|
||||
// 1. During propagation, the use info is used to inform the input node
|
||||
// about what part of the input is used (we call this truncation) and what
|
||||
// is the preferred representation. For conversions that will require
|
||||
// checks, we also keep track of whether a minus zero check is needed.
|
||||
//
|
||||
// 2. During lowering, the use info is used to properly convert the input
|
||||
// to the preferred representation. The preferred representation might be
|
||||
// insufficient to do the conversion (e.g. word32->float64 conv), so we also
|
||||
// need the signedness information to produce the correct value.
|
||||
// Additionally, use info may contain {CheckParameters} which contains
|
||||
// information for the deoptimizer such as a CallIC on which speculation
|
||||
// should be disallowed if the check fails.
|
||||
class UseInfo {
|
||||
public:
|
||||
UseInfo(MachineRepresentation representation, Truncation truncation,
|
||||
TypeCheckKind type_check = TypeCheckKind::kNone,
|
||||
const FeedbackSource& feedback = FeedbackSource())
|
||||
: representation_(representation),
|
||||
truncation_(truncation),
|
||||
type_check_(type_check),
|
||||
feedback_(feedback) {}
|
||||
static UseInfo TruncatingWord32() {
|
||||
return UseInfo(MachineRepresentation::kWord32, Truncation::Word32());
|
||||
}
|
||||
static UseInfo CheckedBigIntTruncatingWord64(const FeedbackSource& feedback) {
|
||||
// Note that Trunction::Word64() can safely use kIdentifyZero, because
|
||||
// TypeCheckKind::kBigInt will make sure we deopt for anything other than
|
||||
// type BigInt anyway.
|
||||
return UseInfo(MachineRepresentation::kWord64, Truncation::Word64(),
|
||||
TypeCheckKind::kBigInt, feedback);
|
||||
}
|
||||
static UseInfo CheckedBigInt64AsWord64(const FeedbackSource& feedback) {
|
||||
return UseInfo(MachineRepresentation::kWord64, Truncation::Any(),
|
||||
TypeCheckKind::kBigInt64, feedback);
|
||||
}
|
||||
static UseInfo Word64() {
|
||||
return UseInfo(MachineRepresentation::kWord64, Truncation::Any());
|
||||
}
|
||||
static UseInfo Word() {
|
||||
return UseInfo(MachineType::PointerRepresentation(), Truncation::Any());
|
||||
}
|
||||
static UseInfo Bool() {
|
||||
return UseInfo(MachineRepresentation::kBit, Truncation::Bool());
|
||||
}
|
||||
static UseInfo Float32() {
|
||||
return UseInfo(MachineRepresentation::kFloat32, Truncation::Any());
|
||||
}
|
||||
static UseInfo Float64() {
|
||||
return UseInfo(MachineRepresentation::kFloat64, Truncation::Any());
|
||||
}
|
||||
static UseInfo TruncatingFloat64(
|
||||
IdentifyZeros identify_zeros = kDistinguishZeros) {
|
||||
return UseInfo(MachineRepresentation::kFloat64,
|
||||
Truncation::OddballAndBigIntToNumber(identify_zeros));
|
||||
}
|
||||
static UseInfo AnyTagged() {
|
||||
return UseInfo(MachineRepresentation::kTagged, Truncation::Any());
|
||||
}
|
||||
static UseInfo TaggedSigned() {
|
||||
return UseInfo(MachineRepresentation::kTaggedSigned, Truncation::Any());
|
||||
}
|
||||
static UseInfo TaggedPointer() {
|
||||
return UseInfo(MachineRepresentation::kTaggedPointer, Truncation::Any());
|
||||
}
|
||||
|
||||
// Possibly deoptimizing conversions.
|
||||
static UseInfo CheckedTaggedAsArrayIndex(const FeedbackSource& feedback) {
|
||||
return UseInfo(MachineType::PointerRepresentation(),
|
||||
Truncation::Any(kIdentifyZeros), TypeCheckKind::kArrayIndex,
|
||||
feedback);
|
||||
}
|
||||
static UseInfo CheckedHeapObjectAsTaggedPointer(
|
||||
const FeedbackSource& feedback) {
|
||||
return UseInfo(MachineRepresentation::kTaggedPointer, Truncation::Any(),
|
||||
TypeCheckKind::kHeapObject, feedback);
|
||||
}
|
||||
|
||||
static UseInfo CheckedBigIntAsTaggedPointer(const FeedbackSource& feedback) {
|
||||
return UseInfo(MachineRepresentation::kTaggedPointer, Truncation::Any(),
|
||||
TypeCheckKind::kBigInt, feedback);
|
||||
}
|
||||
|
||||
static UseInfo CheckedSignedSmallAsTaggedSigned(
|
||||
const FeedbackSource& feedback,
|
||||
IdentifyZeros identify_zeros = kDistinguishZeros) {
|
||||
return UseInfo(MachineRepresentation::kTaggedSigned,
|
||||
Truncation::Any(identify_zeros), TypeCheckKind::kSignedSmall,
|
||||
feedback);
|
||||
}
|
||||
static UseInfo CheckedSignedSmallAsWord32(IdentifyZeros identify_zeros,
|
||||
const FeedbackSource& feedback) {
|
||||
return UseInfo(MachineRepresentation::kWord32,
|
||||
Truncation::Any(identify_zeros), TypeCheckKind::kSignedSmall,
|
||||
feedback);
|
||||
}
|
||||
static UseInfo CheckedSigned32AsWord32(IdentifyZeros identify_zeros,
|
||||
const FeedbackSource& feedback) {
|
||||
return UseInfo(MachineRepresentation::kWord32,
|
||||
Truncation::Any(identify_zeros), TypeCheckKind::kSigned32,
|
||||
feedback);
|
||||
}
|
||||
static UseInfo CheckedSigned64AsWord64(IdentifyZeros identify_zeros,
|
||||
const FeedbackSource& feedback) {
|
||||
return UseInfo(MachineRepresentation::kWord64,
|
||||
Truncation::Any(identify_zeros), TypeCheckKind::kSigned64,
|
||||
feedback);
|
||||
}
|
||||
static UseInfo CheckedNumberAsFloat64(IdentifyZeros identify_zeros,
|
||||
const FeedbackSource& feedback) {
|
||||
return UseInfo(MachineRepresentation::kFloat64,
|
||||
Truncation::Any(identify_zeros), TypeCheckKind::kNumber,
|
||||
feedback);
|
||||
}
|
||||
static UseInfo CheckedNumberAsWord32(const FeedbackSource& feedback) {
|
||||
return UseInfo(MachineRepresentation::kWord32, Truncation::Word32(),
|
||||
TypeCheckKind::kNumber, feedback);
|
||||
}
|
||||
static UseInfo CheckedNumberOrBooleanAsFloat64(
|
||||
IdentifyZeros identify_zeros, const FeedbackSource& feedback) {
|
||||
return UseInfo(MachineRepresentation::kFloat64,
|
||||
Truncation::Any(identify_zeros),
|
||||
TypeCheckKind::kNumberOrBoolean, feedback);
|
||||
}
|
||||
static UseInfo CheckedNumberOrOddballAsFloat64(
|
||||
IdentifyZeros identify_zeros, const FeedbackSource& feedback) {
|
||||
return UseInfo(MachineRepresentation::kFloat64,
|
||||
Truncation::Any(identify_zeros),
|
||||
TypeCheckKind::kNumberOrOddball, feedback);
|
||||
}
|
||||
static UseInfo CheckedNumberOrOddballAsWord32(
|
||||
const FeedbackSource& feedback) {
|
||||
return UseInfo(MachineRepresentation::kWord32, Truncation::Word32(),
|
||||
TypeCheckKind::kNumberOrOddball, feedback);
|
||||
}
|
||||
|
||||
// Undetermined representation.
|
||||
static UseInfo Any() {
|
||||
return UseInfo(MachineRepresentation::kNone, Truncation::Any());
|
||||
}
|
||||
static UseInfo AnyTruncatingToBool() {
|
||||
return UseInfo(MachineRepresentation::kNone, Truncation::Bool());
|
||||
}
|
||||
|
||||
// Value not used.
|
||||
static UseInfo None() {
|
||||
return UseInfo(MachineRepresentation::kNone, Truncation::None());
|
||||
}
|
||||
|
||||
MachineRepresentation representation() const { return representation_; }
|
||||
Truncation truncation() const { return truncation_; }
|
||||
TypeCheckKind type_check() const { return type_check_; }
|
||||
CheckForMinusZeroMode minus_zero_check() const {
|
||||
return truncation().IdentifiesZeroAndMinusZero()
|
||||
? CheckForMinusZeroMode::kDontCheckForMinusZero
|
||||
: CheckForMinusZeroMode::kCheckForMinusZero;
|
||||
}
|
||||
const FeedbackSource& feedback() const { return feedback_; }
|
||||
|
||||
private:
|
||||
MachineRepresentation representation_;
|
||||
Truncation truncation_;
|
||||
TypeCheckKind type_check_;
|
||||
FeedbackSource feedback_;
|
||||
};
|
||||
|
||||
inline bool operator==(const UseInfo& lhs, const UseInfo& rhs) {
|
||||
return lhs.representation() == rhs.representation() &&
|
||||
lhs.truncation() == rhs.truncation() &&
|
||||
lhs.type_check() == rhs.type_check() &&
|
||||
lhs.feedback() == rhs.feedback();
|
||||
}
|
||||
|
||||
inline size_t hash_value(const UseInfo& use_info) {
|
||||
return base::hash_combine(use_info.representation(), use_info.truncation(),
|
||||
use_info.type_check(), use_info.feedback());
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, const UseInfo& use_info) {
|
||||
return os << use_info.representation() << ", " << use_info.truncation()
|
||||
<< ", " << use_info.type_check() << ", " << use_info.feedback();
|
||||
}
|
||||
|
||||
} // namespace v8::internal::compiler
|
||||
|
||||
#endif // V8_COMPILER_USE_INFO_H_
|
Loading…
Reference in New Issue
Block a user