5#ifndef V8_COMPILER_TURBOSHAFT_TYPE_INFERENCE_ANALYSIS_H_
6#define V8_COMPILER_TURBOSHAFT_TYPE_INFERENCE_ANALYSIS_H_
55 block_refinements =
nullptr) {
57 block_refinements_ = block_refinements;
60 for (uint32_t unprocessed_index = 0;
61 unprocessed_index <
graph_.block_count();) {
69 os << block.kind() <<
" " << block.index().id();
81 template <
bool revisit_loop_header>
101 std::optional<table_t::Snapshot> pred_snapshot =
103 if (pred_snapshot.has_value()) {
108 DCHECK(block.IsLoop() && pred == block.LastPredecessor() &&
109 !revisit_loop_header);
121 Type result_type = predecessors[0];
122 for (
size_t i = 1;
i < predecessors.
size(); ++
i) {
134 DCHECK_IMPLIES(revisit_loop_header, block.PredecessorCount() == 2);
135 if (block.PredecessorCount() == 1) {
139 DCHECK(branch->if_true == &block || branch->if_false == &block);
145 bool loop_needs_revisit =
false;
146 auto op_range =
graph_.OperationIndices(block);
147 for (
auto it = op_range.begin(); it != op_range.end(); ++it) {
152 case Opcode::kBranch:
153 case Opcode::kDeoptimize:
154 case Opcode::kDeoptimizeIf:
155 case Opcode::kFrameState:
156 case Opcode::kReturn:
158 case Opcode::kRetain:
159 case Opcode::kUnreachable:
160 case Opcode::kSwitch:
162 case Opcode::kStaticAssert:
163 case Opcode::kDebugBreak:
164 case Opcode::kDebugPrint:
165#if V8_ENABLE_WEBASSEMBLY
166 case Opcode::kGlobalSet:
167 case Opcode::kTrapIf:
169 case Opcode::kCheckException:
173 case Opcode::kCheckTurboshaftTypeOf:
177 case Opcode::kComparison:
180 case Opcode::kConstant:
183 case Opcode::kFloatBinop:
186 case Opcode::kOverflowCheckedBinop:
189 case Opcode::kProjection:
192 case Opcode::kWordBinop:
195 case Opcode::kWord32PairBinop:
196 case Opcode::kAtomicWord32Pair:
197 case Opcode::kPendingLoopPhi:
201 if constexpr (revisit_loop_header) {
208 case Opcode::kGoto: {
218 if (!revisit_loop_header || loop_needs_revisit) {
230 constexpr bool allow_narrowing =
false;
231 constexpr bool is_fallback_for_unsupported_operation =
true;
234 allow_narrowing, is_fallback_for_unsupported_operation);
237 case Opcode::kLoadRootRegister:
244 if constexpr (revisit_loop_header) {
245 if (loop_needs_revisit) {
249 std::min(*unprocessed_index, block.index().id() + 1);
260 "CTOF %3d:%-40s\n P: %3d:%-40s ~~> %s\n", index.id(),
261 graph_.Get(index).ToString().substr(0, 40).c_str(),
263 graph_.Get(check.input()).ToString().substr(0, 40).c_str(),
265 }
else if (check.successful) {
267 "Checking type %s of operation %d:%s failed after it passed in a "
269 check.type.ToString().c_str(), check.input().id(),
270 graph_.Get(check.input()).ToString().c_str());
273 "CTOF %3d:%-40s\n F: %3d:%-40s ~~> %s\n", index.id(),
274 graph_.Get(index).ToString().substr(0, 40).c_str(),
276 graph_.Get(check.input()).ToString().substr(0, 40).c_str(),
292 constant.float64().is_hole_nan()) {
324 "LOOP %3d:%-40s (FIXPOINT)\n N: %-40s ~~> %-40s\n", index.id(),
325 graph_.Get(index).ToString().substr(0, 40).c_str(),
328 constexpr bool allow_narrowing =
true;
329 SetType(index, new_type, allow_narrowing);
335 "LOOP %3d:%-40s (REVISIT)\n W: %-40s ~~> %-40s\n", index.id(),
336 graph_.Get(index).ToString().substr(0, 40).c_str(),
340 new_type =
Widen(old_type, new_type);
365 if (input_type.
IsNone()) {
367 }
else if (input_type.
IsTuple()) {
392 auto MaybeTruncate = [&](
Type t) ->
Type {
393 if (t.IsNone())
return t;
402 for (
size_t i = 1;
i < phi.inputs().
size(); ++
i) {
413 branch->
ToString().substr(0, 40).c_str());
419 then_branch ?
'T' :
'F');
428 char case_for_tracing) {
430 DCHECK(!type.IsInvalid());
434 graph_.Get(op).ToString().substr(0, 40).c_str(),
435 type.ToString().c_str());
438 DCHECK(key_opt.has_value());
442 if (block_refinements_) {
443 (*block_refinements_)[new_block->
index()].emplace_back(op, type);
452 bool is_fallback_for_unsupported_operation =
false) {
465 if (!is_fallback_for_unsupported_operation) {
467 "Type %3d:%-40s ==> %s\n", index.id(),
468 graph_.Get(index).ToString().substr(0, 40).c_str(),
474 "TODO %3d:%-40s ==> %s\n", index.id(),
475 graph_.Get(index).ToString().substr(0, 40).c_str(),
487 if (t.IsInvalid())
return default_type;
505 if (new_type.
IsAny())
return new_type;
509 switch (old_type.
kind()) {
555 block_refinements_ =
nullptr;
void push_back(const T &value)
const Operation & LastOperation(const Graph &graph) const
NeighboringPredecessorIterable PredecessorsIterable() const
Block * LastPredecessor() const
constexpr uint32_t id() const
constexpr bool valid() const
static constexpr RegisterRepresentation Word32()
Key NewKey(KeyData data, Value initial_value=Value{})
const Value & Get(Key key) const
SnapshotTableKey< Type, NoKeyData > Key
void StartNewSnapshot(base::Vector< const Snapshot > predecessors, const ChangeCallback &change_callback={})
bool Set(Key key, Value new_value)
const Type & element(int index) const
void ProcessBlock(const Block &block, uint32_t *unprocessed_index)
void ProcessConstant(OpIndex index, const ConstantOp &constant)
Type ComputeTypeForPhi(const PhiOp &phi)
Type GetTypeAtDefinition(OpIndex index) const
Type GetType(OpIndex index)
Type GetTypeOrDefault(OpIndex index, const Type &default_type)
GrowingOpIndexSidetable< std::optional< table_t::Key > > op_to_key_mapping_
void ProcessCheckTurboshaftTypeOf(OpIndex index, const CheckTurboshaftTypeOfOp &check)
void ProcessComparison(OpIndex index, const ComparisonOp &comparison)
TypeInferenceAnalysis(const Graph &graph, Zone *phase_zone)
const Block * current_block_
void ProcessPhi(OpIndex index, const PhiOp &phi)
ZoneVector< table_t::Snapshot > predecessors_
bool ProcessLoopPhi(OpIndex index, const PhiOp &phi)
void SetType(OpIndex index, Type result_type, bool allow_narrowing=false, bool is_fallback_for_unsupported_operation=false)
GrowingBlockSidetable< std::optional< table_t::Snapshot > > block_to_snapshot_mapping_
void ProcessFloatBinop(OpIndex index, const FloatBinopOp &binop)
void ProcessProjection(OpIndex index, const ProjectionOp &projection)
void ProcessOverflowCheckedBinop(OpIndex index, const OverflowCheckedBinopOp &binop)
void ProcessWordBinop(V< Word > index, const WordBinopOp &binop)
GrowingOpIndexSidetable< Type > types_
void RefineOperationType(const Block *new_block, OpIndex op, const Type &type, char case_for_tracing)
void RefineTypesAfterBranch(const BranchOp *branch, const Block *new_block, bool then_branch)
Type GetTypeOrInvalid(const OpIndex index)
GrowingOpIndexSidetable< Type > Run(GrowingBlockSidetable< std::vector< std::pair< OpIndex, Type > > > *block_refinements=nullptr)
Type Widen(const Type &old_type, const Type &new_type)
const TupleType & AsTuple() const
const Word32Type & AsWord32() const
bool IsSubtypeOf(const Type &other) const
std::string ToString() const
const Word64Type & AsWord64() const
static Type LeastUpperBound(const Type &lhs, const Type &rhs, Zone *zone)
static Type TypeConstant(ConstantOp::Kind kind, ConstantOp::Storage value)
static Type TypeWordBinop(Type left_type, Type right_type, WordBinopOp::Kind kind, WordRepresentation rep, Zone *zone)
static Type TypeOverflowCheckedBinop(const Type &left_type, const Type &right_type, OverflowCheckedBinopOp::Kind kind, WordRepresentation rep, Zone *zone)
static Type TypeComparison(const Type &lhs, const Type &rhs, RegisterRepresentation rep, ComparisonOp::Kind kind, Zone *zone)
static Type TypeForRepresentation(RegisterRepresentation rep)
static Type TypeFloatBinop(Type left_type, Type right_type, FloatBinopOp::Kind kind, FloatRepresentation rep, Zone *zone)
static Word32Type TruncateWord32Input(const Type &input, bool implicit_word64_narrowing, Zone *zone)
#define TURBOSHAFT_TRACE_TYPING_OK(str,...)
#define TURBOSHAFT_TRACE_TYPING(...)
#define TURBOSHAFT_TRACE_TYPING_FAIL(str,...)
constexpr Vector< T > VectorOf(T *start, size_t size)
V8_EXPORT_PRIVATE FlagValues v8_flags
#define DCHECK_NOT_NULL(val)
#define DCHECK_IMPLIES(v1, v2)
#define DCHECK(condition)
#define DCHECK_LT(v1, v2)
#define DCHECK_EQ(v1, v2)
#define DCHECK_GT(v1, v2)
V< Word32 > condition() const
RegisterRepresentation rep
std::string ToString() const
const underlying_operation_t< Op > * TryCast() const
underlying_operation_t< Op > & Cast()
base::Vector< const RegisterRepresentation > outputs_rep() const
RegisterRepresentation rep
V< WordType > left() const
V< WordType > right() const
static type_t WidenMaximal(const type_t &old_type, const type_t &new_type, Zone *zone)
#define V8_UNLIKELY(condition)