11cb0ef41Sopenharmony_ci// Copyright 2014 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci#include "src/compiler/simplified-lowering.h" 61cb0ef41Sopenharmony_ci 71cb0ef41Sopenharmony_ci#include <limits> 81cb0ef41Sopenharmony_ci 91cb0ef41Sopenharmony_ci#include "include/v8-fast-api-calls.h" 101cb0ef41Sopenharmony_ci#include "src/base/bits.h" 111cb0ef41Sopenharmony_ci#include "src/base/small-vector.h" 121cb0ef41Sopenharmony_ci#include "src/codegen/code-factory.h" 131cb0ef41Sopenharmony_ci#include "src/codegen/machine-type.h" 141cb0ef41Sopenharmony_ci#include "src/codegen/tick-counter.h" 151cb0ef41Sopenharmony_ci#include "src/compiler/access-builder.h" 161cb0ef41Sopenharmony_ci#include "src/compiler/common-operator.h" 171cb0ef41Sopenharmony_ci#include "src/compiler/compiler-source-position-table.h" 181cb0ef41Sopenharmony_ci#include "src/compiler/diamond.h" 191cb0ef41Sopenharmony_ci#include "src/compiler/graph-visualizer.h" 201cb0ef41Sopenharmony_ci#include "src/compiler/js-heap-broker.h" 211cb0ef41Sopenharmony_ci#include "src/compiler/linkage.h" 221cb0ef41Sopenharmony_ci#include "src/compiler/node-matchers.h" 231cb0ef41Sopenharmony_ci#include "src/compiler/node-observer.h" 241cb0ef41Sopenharmony_ci#include "src/compiler/node-origin-table.h" 251cb0ef41Sopenharmony_ci#include "src/compiler/operation-typer.h" 261cb0ef41Sopenharmony_ci#include "src/compiler/operator-properties.h" 271cb0ef41Sopenharmony_ci#include "src/compiler/representation-change.h" 281cb0ef41Sopenharmony_ci#include "src/compiler/simplified-lowering-verifier.h" 291cb0ef41Sopenharmony_ci#include "src/compiler/simplified-operator.h" 301cb0ef41Sopenharmony_ci#include "src/compiler/type-cache.h" 311cb0ef41Sopenharmony_ci#include "src/numbers/conversions-inl.h" 321cb0ef41Sopenharmony_ci#include "src/objects/objects.h" 331cb0ef41Sopenharmony_ci#include "src/utils/address-map.h" 341cb0ef41Sopenharmony_ci 351cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY 361cb0ef41Sopenharmony_ci#include "src/wasm/value-type.h" 371cb0ef41Sopenharmony_ci#endif // V8_ENABLE_WEBASSEMBLY 381cb0ef41Sopenharmony_ci 391cb0ef41Sopenharmony_cinamespace v8 { 401cb0ef41Sopenharmony_cinamespace internal { 411cb0ef41Sopenharmony_cinamespace compiler { 421cb0ef41Sopenharmony_ci 431cb0ef41Sopenharmony_ci// Macro for outputting trace information from representation inference. 441cb0ef41Sopenharmony_ci#define TRACE(...) \ 451cb0ef41Sopenharmony_ci do { \ 461cb0ef41Sopenharmony_ci if (FLAG_trace_representation) PrintF(__VA_ARGS__); \ 471cb0ef41Sopenharmony_ci } while (false) 481cb0ef41Sopenharmony_ci 491cb0ef41Sopenharmony_ciconst char* kSimplifiedLoweringReducerName = "SimplifiedLowering"; 501cb0ef41Sopenharmony_ci 511cb0ef41Sopenharmony_ci// Representation selection and lowering of {Simplified} operators to machine 521cb0ef41Sopenharmony_ci// operators are interwined. We use a fixpoint calculation to compute both the 531cb0ef41Sopenharmony_ci// output representation and the best possible lowering for {Simplified} nodes. 541cb0ef41Sopenharmony_ci// Representation change insertion ensures that all values are in the correct 551cb0ef41Sopenharmony_ci// machine representation after this phase, as dictated by the machine 561cb0ef41Sopenharmony_ci// operators themselves. 571cb0ef41Sopenharmony_cienum Phase { 581cb0ef41Sopenharmony_ci // 1.) PROPAGATE: Traverse the graph from the end, pushing usage information 591cb0ef41Sopenharmony_ci // backwards from uses to definitions, around cycles in phis, according 601cb0ef41Sopenharmony_ci // to local rules for each operator. 611cb0ef41Sopenharmony_ci // During this phase, the usage information for a node determines the best 621cb0ef41Sopenharmony_ci // possible lowering for each operator so far, and that in turn determines 631cb0ef41Sopenharmony_ci // the output representation. 641cb0ef41Sopenharmony_ci // Therefore, to be correct, this phase must iterate to a fixpoint before 651cb0ef41Sopenharmony_ci // the next phase can begin. 661cb0ef41Sopenharmony_ci PROPAGATE, 671cb0ef41Sopenharmony_ci 681cb0ef41Sopenharmony_ci // 2.) RETYPE: Propagate types from type feedback forwards. 691cb0ef41Sopenharmony_ci RETYPE, 701cb0ef41Sopenharmony_ci 711cb0ef41Sopenharmony_ci // 3.) LOWER: perform lowering for all {Simplified} nodes by replacing some 721cb0ef41Sopenharmony_ci // operators for some nodes, expanding some nodes to multiple nodes, or 731cb0ef41Sopenharmony_ci // removing some (redundant) nodes. 741cb0ef41Sopenharmony_ci // During this phase, use the {RepresentationChanger} to insert 751cb0ef41Sopenharmony_ci // representation changes between uses that demand a particular 761cb0ef41Sopenharmony_ci // representation and nodes that produce a different representation. 771cb0ef41Sopenharmony_ci LOWER 781cb0ef41Sopenharmony_ci}; 791cb0ef41Sopenharmony_ci 801cb0ef41Sopenharmony_cinamespace { 811cb0ef41Sopenharmony_ci 821cb0ef41Sopenharmony_ciMachineRepresentation MachineRepresentationFromArrayType( 831cb0ef41Sopenharmony_ci ExternalArrayType array_type) { 841cb0ef41Sopenharmony_ci switch (array_type) { 851cb0ef41Sopenharmony_ci case kExternalUint8Array: 861cb0ef41Sopenharmony_ci case kExternalUint8ClampedArray: 871cb0ef41Sopenharmony_ci case kExternalInt8Array: 881cb0ef41Sopenharmony_ci return MachineRepresentation::kWord8; 891cb0ef41Sopenharmony_ci case kExternalUint16Array: 901cb0ef41Sopenharmony_ci case kExternalInt16Array: 911cb0ef41Sopenharmony_ci return MachineRepresentation::kWord16; 921cb0ef41Sopenharmony_ci case kExternalUint32Array: 931cb0ef41Sopenharmony_ci case kExternalInt32Array: 941cb0ef41Sopenharmony_ci return MachineRepresentation::kWord32; 951cb0ef41Sopenharmony_ci case kExternalFloat32Array: 961cb0ef41Sopenharmony_ci return MachineRepresentation::kFloat32; 971cb0ef41Sopenharmony_ci case kExternalFloat64Array: 981cb0ef41Sopenharmony_ci return MachineRepresentation::kFloat64; 991cb0ef41Sopenharmony_ci case kExternalBigInt64Array: 1001cb0ef41Sopenharmony_ci case kExternalBigUint64Array: 1011cb0ef41Sopenharmony_ci UNIMPLEMENTED(); 1021cb0ef41Sopenharmony_ci } 1031cb0ef41Sopenharmony_ci UNREACHABLE(); 1041cb0ef41Sopenharmony_ci} 1051cb0ef41Sopenharmony_ci 1061cb0ef41Sopenharmony_ciUseInfo CheckedUseInfoAsWord32FromHint( 1071cb0ef41Sopenharmony_ci NumberOperationHint hint, IdentifyZeros identify_zeros = kDistinguishZeros, 1081cb0ef41Sopenharmony_ci const FeedbackSource& feedback = FeedbackSource()) { 1091cb0ef41Sopenharmony_ci switch (hint) { 1101cb0ef41Sopenharmony_ci case NumberOperationHint::kSignedSmall: 1111cb0ef41Sopenharmony_ci case NumberOperationHint::kSignedSmallInputs: 1121cb0ef41Sopenharmony_ci return UseInfo::CheckedSignedSmallAsWord32(identify_zeros, feedback); 1131cb0ef41Sopenharmony_ci case NumberOperationHint::kNumber: 1141cb0ef41Sopenharmony_ci DCHECK_EQ(identify_zeros, kIdentifyZeros); 1151cb0ef41Sopenharmony_ci return UseInfo::CheckedNumberAsWord32(feedback); 1161cb0ef41Sopenharmony_ci case NumberOperationHint::kNumberOrBoolean: 1171cb0ef41Sopenharmony_ci // Not used currently. 1181cb0ef41Sopenharmony_ci UNREACHABLE(); 1191cb0ef41Sopenharmony_ci case NumberOperationHint::kNumberOrOddball: 1201cb0ef41Sopenharmony_ci DCHECK_EQ(identify_zeros, kIdentifyZeros); 1211cb0ef41Sopenharmony_ci return UseInfo::CheckedNumberOrOddballAsWord32(feedback); 1221cb0ef41Sopenharmony_ci } 1231cb0ef41Sopenharmony_ci UNREACHABLE(); 1241cb0ef41Sopenharmony_ci} 1251cb0ef41Sopenharmony_ci 1261cb0ef41Sopenharmony_ciUseInfo CheckedUseInfoAsFloat64FromHint( 1271cb0ef41Sopenharmony_ci NumberOperationHint hint, const FeedbackSource& feedback, 1281cb0ef41Sopenharmony_ci IdentifyZeros identify_zeros = kDistinguishZeros) { 1291cb0ef41Sopenharmony_ci switch (hint) { 1301cb0ef41Sopenharmony_ci case NumberOperationHint::kSignedSmall: 1311cb0ef41Sopenharmony_ci case NumberOperationHint::kSignedSmallInputs: 1321cb0ef41Sopenharmony_ci // Not used currently. 1331cb0ef41Sopenharmony_ci UNREACHABLE(); 1341cb0ef41Sopenharmony_ci case NumberOperationHint::kNumber: 1351cb0ef41Sopenharmony_ci return UseInfo::CheckedNumberAsFloat64(identify_zeros, feedback); 1361cb0ef41Sopenharmony_ci case NumberOperationHint::kNumberOrBoolean: 1371cb0ef41Sopenharmony_ci return UseInfo::CheckedNumberOrBooleanAsFloat64(identify_zeros, feedback); 1381cb0ef41Sopenharmony_ci case NumberOperationHint::kNumberOrOddball: 1391cb0ef41Sopenharmony_ci return UseInfo::CheckedNumberOrOddballAsFloat64(identify_zeros, feedback); 1401cb0ef41Sopenharmony_ci } 1411cb0ef41Sopenharmony_ci UNREACHABLE(); 1421cb0ef41Sopenharmony_ci} 1431cb0ef41Sopenharmony_ci 1441cb0ef41Sopenharmony_ciUseInfo TruncatingUseInfoFromRepresentation(MachineRepresentation rep) { 1451cb0ef41Sopenharmony_ci switch (rep) { 1461cb0ef41Sopenharmony_ci case MachineRepresentation::kTaggedSigned: 1471cb0ef41Sopenharmony_ci return UseInfo::TaggedSigned(); 1481cb0ef41Sopenharmony_ci case MachineRepresentation::kTaggedPointer: 1491cb0ef41Sopenharmony_ci case MachineRepresentation::kTagged: 1501cb0ef41Sopenharmony_ci case MachineRepresentation::kMapWord: 1511cb0ef41Sopenharmony_ci return UseInfo::AnyTagged(); 1521cb0ef41Sopenharmony_ci case MachineRepresentation::kFloat64: 1531cb0ef41Sopenharmony_ci return UseInfo::TruncatingFloat64(); 1541cb0ef41Sopenharmony_ci case MachineRepresentation::kFloat32: 1551cb0ef41Sopenharmony_ci return UseInfo::Float32(); 1561cb0ef41Sopenharmony_ci case MachineRepresentation::kWord8: 1571cb0ef41Sopenharmony_ci case MachineRepresentation::kWord16: 1581cb0ef41Sopenharmony_ci case MachineRepresentation::kWord32: 1591cb0ef41Sopenharmony_ci return UseInfo::TruncatingWord32(); 1601cb0ef41Sopenharmony_ci case MachineRepresentation::kWord64: 1611cb0ef41Sopenharmony_ci return UseInfo::Word64(); 1621cb0ef41Sopenharmony_ci case MachineRepresentation::kBit: 1631cb0ef41Sopenharmony_ci return UseInfo::Bool(); 1641cb0ef41Sopenharmony_ci case MachineRepresentation::kCompressedPointer: 1651cb0ef41Sopenharmony_ci case MachineRepresentation::kCompressed: 1661cb0ef41Sopenharmony_ci case MachineRepresentation::kSandboxedPointer: 1671cb0ef41Sopenharmony_ci case MachineRepresentation::kSimd128: 1681cb0ef41Sopenharmony_ci case MachineRepresentation::kNone: 1691cb0ef41Sopenharmony_ci break; 1701cb0ef41Sopenharmony_ci } 1711cb0ef41Sopenharmony_ci UNREACHABLE(); 1721cb0ef41Sopenharmony_ci} 1731cb0ef41Sopenharmony_ci 1741cb0ef41Sopenharmony_ciUseInfo UseInfoForBasePointer(const FieldAccess& access) { 1751cb0ef41Sopenharmony_ci return access.tag() != 0 ? UseInfo::AnyTagged() : UseInfo::Word(); 1761cb0ef41Sopenharmony_ci} 1771cb0ef41Sopenharmony_ci 1781cb0ef41Sopenharmony_ciUseInfo UseInfoForBasePointer(const ElementAccess& access) { 1791cb0ef41Sopenharmony_ci return access.tag() != 0 ? UseInfo::AnyTagged() : UseInfo::Word(); 1801cb0ef41Sopenharmony_ci} 1811cb0ef41Sopenharmony_ci 1821cb0ef41Sopenharmony_civoid ReplaceEffectControlUses(Node* node, Node* effect, Node* control) { 1831cb0ef41Sopenharmony_ci for (Edge edge : node->use_edges()) { 1841cb0ef41Sopenharmony_ci if (NodeProperties::IsControlEdge(edge)) { 1851cb0ef41Sopenharmony_ci edge.UpdateTo(control); 1861cb0ef41Sopenharmony_ci } else if (NodeProperties::IsEffectEdge(edge)) { 1871cb0ef41Sopenharmony_ci edge.UpdateTo(effect); 1881cb0ef41Sopenharmony_ci } else { 1891cb0ef41Sopenharmony_ci DCHECK(NodeProperties::IsValueEdge(edge) || 1901cb0ef41Sopenharmony_ci NodeProperties::IsContextEdge(edge)); 1911cb0ef41Sopenharmony_ci } 1921cb0ef41Sopenharmony_ci } 1931cb0ef41Sopenharmony_ci} 1941cb0ef41Sopenharmony_ci 1951cb0ef41Sopenharmony_cibool CanOverflowSigned32(const Operator* op, Type left, Type right, 1961cb0ef41Sopenharmony_ci TypeCache const* type_cache, Zone* type_zone) { 1971cb0ef41Sopenharmony_ci // We assume the inputs are checked Signed32 (or known statically to be 1981cb0ef41Sopenharmony_ci // Signed32). Technically, the inputs could also be minus zero, which we treat 1991cb0ef41Sopenharmony_ci // as 0 for the purpose of this function. 2001cb0ef41Sopenharmony_ci if (left.Maybe(Type::MinusZero())) { 2011cb0ef41Sopenharmony_ci left = Type::Union(left, type_cache->kSingletonZero, type_zone); 2021cb0ef41Sopenharmony_ci } 2031cb0ef41Sopenharmony_ci if (right.Maybe(Type::MinusZero())) { 2041cb0ef41Sopenharmony_ci right = Type::Union(right, type_cache->kSingletonZero, type_zone); 2051cb0ef41Sopenharmony_ci } 2061cb0ef41Sopenharmony_ci left = Type::Intersect(left, Type::Signed32(), type_zone); 2071cb0ef41Sopenharmony_ci right = Type::Intersect(right, Type::Signed32(), type_zone); 2081cb0ef41Sopenharmony_ci if (left.IsNone() || right.IsNone()) return false; 2091cb0ef41Sopenharmony_ci switch (op->opcode()) { 2101cb0ef41Sopenharmony_ci case IrOpcode::kSpeculativeSafeIntegerAdd: 2111cb0ef41Sopenharmony_ci return (left.Max() + right.Max() > kMaxInt) || 2121cb0ef41Sopenharmony_ci (left.Min() + right.Min() < kMinInt); 2131cb0ef41Sopenharmony_ci 2141cb0ef41Sopenharmony_ci case IrOpcode::kSpeculativeSafeIntegerSubtract: 2151cb0ef41Sopenharmony_ci return (left.Max() - right.Min() > kMaxInt) || 2161cb0ef41Sopenharmony_ci (left.Min() - right.Max() < kMinInt); 2171cb0ef41Sopenharmony_ci 2181cb0ef41Sopenharmony_ci default: 2191cb0ef41Sopenharmony_ci UNREACHABLE(); 2201cb0ef41Sopenharmony_ci } 2211cb0ef41Sopenharmony_ci} 2221cb0ef41Sopenharmony_ci 2231cb0ef41Sopenharmony_cibool IsSomePositiveOrderedNumber(Type type) { 2241cb0ef41Sopenharmony_ci return type.Is(Type::OrderedNumber()) && (type.IsNone() || type.Min() > 0); 2251cb0ef41Sopenharmony_ci} 2261cb0ef41Sopenharmony_ci 2271cb0ef41Sopenharmony_ciclass JSONGraphWriterWithVerifierTypes : public JSONGraphWriter { 2281cb0ef41Sopenharmony_ci public: 2291cb0ef41Sopenharmony_ci JSONGraphWriterWithVerifierTypes(std::ostream& os, const Graph* graph, 2301cb0ef41Sopenharmony_ci const SourcePositionTable* positions, 2311cb0ef41Sopenharmony_ci const NodeOriginTable* origins, 2321cb0ef41Sopenharmony_ci SimplifiedLoweringVerifier* verifier) 2331cb0ef41Sopenharmony_ci : JSONGraphWriter(os, graph, positions, origins), verifier_(verifier) {} 2341cb0ef41Sopenharmony_ci 2351cb0ef41Sopenharmony_ci protected: 2361cb0ef41Sopenharmony_ci base::Optional<Type> GetType(Node* node) override { 2371cb0ef41Sopenharmony_ci return verifier_->GetType(node); 2381cb0ef41Sopenharmony_ci } 2391cb0ef41Sopenharmony_ci 2401cb0ef41Sopenharmony_ci private: 2411cb0ef41Sopenharmony_ci SimplifiedLoweringVerifier* verifier_; 2421cb0ef41Sopenharmony_ci}; 2431cb0ef41Sopenharmony_ci 2441cb0ef41Sopenharmony_ci} // namespace 2451cb0ef41Sopenharmony_ci 2461cb0ef41Sopenharmony_ci#ifdef DEBUG 2471cb0ef41Sopenharmony_ci// Helpers for monotonicity checking. 2481cb0ef41Sopenharmony_ciclass InputUseInfos { 2491cb0ef41Sopenharmony_ci public: 2501cb0ef41Sopenharmony_ci explicit InputUseInfos(Zone* zone) : input_use_infos_(zone) {} 2511cb0ef41Sopenharmony_ci 2521cb0ef41Sopenharmony_ci void SetAndCheckInput(Node* node, int index, UseInfo use_info) { 2531cb0ef41Sopenharmony_ci if (input_use_infos_.empty()) { 2541cb0ef41Sopenharmony_ci input_use_infos_.resize(node->InputCount(), UseInfo::None()); 2551cb0ef41Sopenharmony_ci } 2561cb0ef41Sopenharmony_ci // Check that the new use informatin is a super-type of the old 2571cb0ef41Sopenharmony_ci // one. 2581cb0ef41Sopenharmony_ci DCHECK(IsUseLessGeneral(input_use_infos_[index], use_info)); 2591cb0ef41Sopenharmony_ci input_use_infos_[index] = use_info; 2601cb0ef41Sopenharmony_ci } 2611cb0ef41Sopenharmony_ci 2621cb0ef41Sopenharmony_ci private: 2631cb0ef41Sopenharmony_ci ZoneVector<UseInfo> input_use_infos_; 2641cb0ef41Sopenharmony_ci 2651cb0ef41Sopenharmony_ci static bool IsUseLessGeneral(UseInfo use1, UseInfo use2) { 2661cb0ef41Sopenharmony_ci return use1.truncation().IsLessGeneralThan(use2.truncation()); 2671cb0ef41Sopenharmony_ci } 2681cb0ef41Sopenharmony_ci}; 2691cb0ef41Sopenharmony_ci 2701cb0ef41Sopenharmony_ci#endif // DEBUG 2711cb0ef41Sopenharmony_ci 2721cb0ef41Sopenharmony_ciclass RepresentationSelector { 2731cb0ef41Sopenharmony_ci // The purpose of this nested class is to hide method 2741cb0ef41Sopenharmony_ci // v8::internal::compiler::NodeProperties::ChangeOp which should not be 2751cb0ef41Sopenharmony_ci // directly used by code in RepresentationSelector and SimplifiedLowering. 2761cb0ef41Sopenharmony_ci // RepresentationSelector code should call RepresentationSelector::ChangeOp in 2771cb0ef41Sopenharmony_ci // place of NodeProperties::ChangeOp, in order to notify the changes to a 2781cb0ef41Sopenharmony_ci // registered ObserveNodeManager and support the %ObserveNode intrinsic. 2791cb0ef41Sopenharmony_ci class NodeProperties : public compiler::NodeProperties { 2801cb0ef41Sopenharmony_ci static void ChangeOp(Node* node, const Operator* new_op) { UNREACHABLE(); } 2811cb0ef41Sopenharmony_ci }; 2821cb0ef41Sopenharmony_ci 2831cb0ef41Sopenharmony_ci public: 2841cb0ef41Sopenharmony_ci // Information for each node tracked during the fixpoint. 2851cb0ef41Sopenharmony_ci class NodeInfo final { 2861cb0ef41Sopenharmony_ci public: 2871cb0ef41Sopenharmony_ci // Adds new use to the node. Returns true if something has changed 2881cb0ef41Sopenharmony_ci // and the node has to be requeued. 2891cb0ef41Sopenharmony_ci bool AddUse(UseInfo info) { 2901cb0ef41Sopenharmony_ci Truncation old_truncation = truncation_; 2911cb0ef41Sopenharmony_ci truncation_ = Truncation::Generalize(truncation_, info.truncation()); 2921cb0ef41Sopenharmony_ci return truncation_ != old_truncation; 2931cb0ef41Sopenharmony_ci } 2941cb0ef41Sopenharmony_ci 2951cb0ef41Sopenharmony_ci void set_queued() { state_ = kQueued; } 2961cb0ef41Sopenharmony_ci void set_visited() { state_ = kVisited; } 2971cb0ef41Sopenharmony_ci void set_pushed() { state_ = kPushed; } 2981cb0ef41Sopenharmony_ci void reset_state() { state_ = kUnvisited; } 2991cb0ef41Sopenharmony_ci bool visited() const { return state_ == kVisited; } 3001cb0ef41Sopenharmony_ci bool queued() const { return state_ == kQueued; } 3011cb0ef41Sopenharmony_ci bool pushed() const { return state_ == kPushed; } 3021cb0ef41Sopenharmony_ci bool unvisited() const { return state_ == kUnvisited; } 3031cb0ef41Sopenharmony_ci Truncation truncation() const { return truncation_; } 3041cb0ef41Sopenharmony_ci void set_output(MachineRepresentation output) { representation_ = output; } 3051cb0ef41Sopenharmony_ci 3061cb0ef41Sopenharmony_ci MachineRepresentation representation() const { return representation_; } 3071cb0ef41Sopenharmony_ci 3081cb0ef41Sopenharmony_ci // Helpers for feedback typing. 3091cb0ef41Sopenharmony_ci void set_feedback_type(Type type) { feedback_type_ = type; } 3101cb0ef41Sopenharmony_ci Type feedback_type() const { return feedback_type_; } 3111cb0ef41Sopenharmony_ci void set_weakened() { weakened_ = true; } 3121cb0ef41Sopenharmony_ci bool weakened() const { return weakened_; } 3131cb0ef41Sopenharmony_ci void set_restriction_type(Type type) { restriction_type_ = type; } 3141cb0ef41Sopenharmony_ci Type restriction_type() const { return restriction_type_; } 3151cb0ef41Sopenharmony_ci 3161cb0ef41Sopenharmony_ci private: 3171cb0ef41Sopenharmony_ci // Fields are ordered to avoid mixing byte and word size fields to minimize 3181cb0ef41Sopenharmony_ci // padding. 3191cb0ef41Sopenharmony_ci enum State : uint8_t { kUnvisited, kPushed, kVisited, kQueued }; 3201cb0ef41Sopenharmony_ci State state_ = kUnvisited; 3211cb0ef41Sopenharmony_ci MachineRepresentation representation_ = 3221cb0ef41Sopenharmony_ci MachineRepresentation::kNone; // Output representation. 3231cb0ef41Sopenharmony_ci Truncation truncation_ = Truncation::None(); // Information about uses. 3241cb0ef41Sopenharmony_ci bool weakened_ = false; 3251cb0ef41Sopenharmony_ci 3261cb0ef41Sopenharmony_ci Type restriction_type_ = Type::Any(); 3271cb0ef41Sopenharmony_ci Type feedback_type_; 3281cb0ef41Sopenharmony_ci }; 3291cb0ef41Sopenharmony_ci 3301cb0ef41Sopenharmony_ci RepresentationSelector(JSGraph* jsgraph, JSHeapBroker* broker, Zone* zone, 3311cb0ef41Sopenharmony_ci RepresentationChanger* changer, 3321cb0ef41Sopenharmony_ci SourcePositionTable* source_positions, 3331cb0ef41Sopenharmony_ci NodeOriginTable* node_origins, 3341cb0ef41Sopenharmony_ci TickCounter* tick_counter, Linkage* linkage, 3351cb0ef41Sopenharmony_ci ObserveNodeManager* observe_node_manager, 3361cb0ef41Sopenharmony_ci SimplifiedLoweringVerifier* verifier) 3371cb0ef41Sopenharmony_ci : jsgraph_(jsgraph), 3381cb0ef41Sopenharmony_ci broker_(broker), 3391cb0ef41Sopenharmony_ci zone_(zone), 3401cb0ef41Sopenharmony_ci might_need_revisit_(zone), 3411cb0ef41Sopenharmony_ci count_(jsgraph->graph()->NodeCount()), 3421cb0ef41Sopenharmony_ci info_(count_, zone), 3431cb0ef41Sopenharmony_ci#ifdef DEBUG 3441cb0ef41Sopenharmony_ci node_input_use_infos_(count_, InputUseInfos(zone), zone), 3451cb0ef41Sopenharmony_ci#endif 3461cb0ef41Sopenharmony_ci replacements_(zone), 3471cb0ef41Sopenharmony_ci changer_(changer), 3481cb0ef41Sopenharmony_ci revisit_queue_(zone), 3491cb0ef41Sopenharmony_ci traversal_nodes_(zone), 3501cb0ef41Sopenharmony_ci source_positions_(source_positions), 3511cb0ef41Sopenharmony_ci node_origins_(node_origins), 3521cb0ef41Sopenharmony_ci type_cache_(TypeCache::Get()), 3531cb0ef41Sopenharmony_ci op_typer_(broker, graph_zone()), 3541cb0ef41Sopenharmony_ci tick_counter_(tick_counter), 3551cb0ef41Sopenharmony_ci linkage_(linkage), 3561cb0ef41Sopenharmony_ci observe_node_manager_(observe_node_manager), 3571cb0ef41Sopenharmony_ci verifier_(verifier) { 3581cb0ef41Sopenharmony_ci } 3591cb0ef41Sopenharmony_ci 3601cb0ef41Sopenharmony_ci bool verification_enabled() const { return verifier_ != nullptr; } 3611cb0ef41Sopenharmony_ci 3621cb0ef41Sopenharmony_ci void ResetNodeInfoState() { 3631cb0ef41Sopenharmony_ci // Clean up for the next phase. 3641cb0ef41Sopenharmony_ci for (NodeInfo& info : info_) { 3651cb0ef41Sopenharmony_ci info.reset_state(); 3661cb0ef41Sopenharmony_ci } 3671cb0ef41Sopenharmony_ci } 3681cb0ef41Sopenharmony_ci 3691cb0ef41Sopenharmony_ci Type TypeOf(Node* node) { 3701cb0ef41Sopenharmony_ci Type type = GetInfo(node)->feedback_type(); 3711cb0ef41Sopenharmony_ci return type.IsInvalid() ? NodeProperties::GetType(node) : type; 3721cb0ef41Sopenharmony_ci } 3731cb0ef41Sopenharmony_ci 3741cb0ef41Sopenharmony_ci Type FeedbackTypeOf(Node* node) { 3751cb0ef41Sopenharmony_ci Type type = GetInfo(node)->feedback_type(); 3761cb0ef41Sopenharmony_ci return type.IsInvalid() ? Type::None() : type; 3771cb0ef41Sopenharmony_ci } 3781cb0ef41Sopenharmony_ci 3791cb0ef41Sopenharmony_ci Type TypePhi(Node* node) { 3801cb0ef41Sopenharmony_ci int arity = node->op()->ValueInputCount(); 3811cb0ef41Sopenharmony_ci Type type = FeedbackTypeOf(node->InputAt(0)); 3821cb0ef41Sopenharmony_ci for (int i = 1; i < arity; ++i) { 3831cb0ef41Sopenharmony_ci type = op_typer_.Merge(type, FeedbackTypeOf(node->InputAt(i))); 3841cb0ef41Sopenharmony_ci } 3851cb0ef41Sopenharmony_ci return type; 3861cb0ef41Sopenharmony_ci } 3871cb0ef41Sopenharmony_ci 3881cb0ef41Sopenharmony_ci Type TypeSelect(Node* node) { 3891cb0ef41Sopenharmony_ci return op_typer_.Merge(FeedbackTypeOf(node->InputAt(1)), 3901cb0ef41Sopenharmony_ci FeedbackTypeOf(node->InputAt(2))); 3911cb0ef41Sopenharmony_ci } 3921cb0ef41Sopenharmony_ci 3931cb0ef41Sopenharmony_ci bool UpdateFeedbackType(Node* node) { 3941cb0ef41Sopenharmony_ci if (node->op()->ValueOutputCount() == 0) return false; 3951cb0ef41Sopenharmony_ci 3961cb0ef41Sopenharmony_ci // For any non-phi node just wait until we get all inputs typed. We only 3971cb0ef41Sopenharmony_ci // allow untyped inputs for phi nodes because phis are the only places 3981cb0ef41Sopenharmony_ci // where cycles need to be broken. 3991cb0ef41Sopenharmony_ci if (node->opcode() != IrOpcode::kPhi) { 4001cb0ef41Sopenharmony_ci for (int i = 0; i < node->op()->ValueInputCount(); i++) { 4011cb0ef41Sopenharmony_ci if (GetInfo(node->InputAt(i))->feedback_type().IsInvalid()) { 4021cb0ef41Sopenharmony_ci return false; 4031cb0ef41Sopenharmony_ci } 4041cb0ef41Sopenharmony_ci } 4051cb0ef41Sopenharmony_ci } 4061cb0ef41Sopenharmony_ci 4071cb0ef41Sopenharmony_ci NodeInfo* info = GetInfo(node); 4081cb0ef41Sopenharmony_ci Type type = info->feedback_type(); 4091cb0ef41Sopenharmony_ci Type new_type = NodeProperties::GetType(node); 4101cb0ef41Sopenharmony_ci 4111cb0ef41Sopenharmony_ci // We preload these values here to avoid increasing the binary size too 4121cb0ef41Sopenharmony_ci // much, which happens if we inline the calls into the macros below. 4131cb0ef41Sopenharmony_ci Type input0_type; 4141cb0ef41Sopenharmony_ci if (node->InputCount() > 0) input0_type = FeedbackTypeOf(node->InputAt(0)); 4151cb0ef41Sopenharmony_ci Type input1_type; 4161cb0ef41Sopenharmony_ci if (node->InputCount() > 1) input1_type = FeedbackTypeOf(node->InputAt(1)); 4171cb0ef41Sopenharmony_ci 4181cb0ef41Sopenharmony_ci switch (node->opcode()) { 4191cb0ef41Sopenharmony_ci#define DECLARE_CASE(Name) \ 4201cb0ef41Sopenharmony_ci case IrOpcode::k##Name: { \ 4211cb0ef41Sopenharmony_ci new_type = op_typer_.Name(input0_type, input1_type); \ 4221cb0ef41Sopenharmony_ci break; \ 4231cb0ef41Sopenharmony_ci } 4241cb0ef41Sopenharmony_ci SIMPLIFIED_NUMBER_BINOP_LIST(DECLARE_CASE) 4251cb0ef41Sopenharmony_ci DECLARE_CASE(SameValue) 4261cb0ef41Sopenharmony_ci#undef DECLARE_CASE 4271cb0ef41Sopenharmony_ci 4281cb0ef41Sopenharmony_ci#define DECLARE_CASE(Name) \ 4291cb0ef41Sopenharmony_ci case IrOpcode::k##Name: { \ 4301cb0ef41Sopenharmony_ci new_type = Type::Intersect(op_typer_.Name(input0_type, input1_type), \ 4311cb0ef41Sopenharmony_ci info->restriction_type(), graph_zone()); \ 4321cb0ef41Sopenharmony_ci break; \ 4331cb0ef41Sopenharmony_ci } 4341cb0ef41Sopenharmony_ci SIMPLIFIED_SPECULATIVE_NUMBER_BINOP_LIST(DECLARE_CASE) 4351cb0ef41Sopenharmony_ci SIMPLIFIED_SPECULATIVE_BIGINT_BINOP_LIST(DECLARE_CASE) 4361cb0ef41Sopenharmony_ci#undef DECLARE_CASE 4371cb0ef41Sopenharmony_ci 4381cb0ef41Sopenharmony_ci#define DECLARE_CASE(Name) \ 4391cb0ef41Sopenharmony_ci case IrOpcode::k##Name: { \ 4401cb0ef41Sopenharmony_ci new_type = op_typer_.Name(input0_type); \ 4411cb0ef41Sopenharmony_ci break; \ 4421cb0ef41Sopenharmony_ci } 4431cb0ef41Sopenharmony_ci SIMPLIFIED_NUMBER_UNOP_LIST(DECLARE_CASE) 4441cb0ef41Sopenharmony_ci#undef DECLARE_CASE 4451cb0ef41Sopenharmony_ci 4461cb0ef41Sopenharmony_ci#define DECLARE_CASE(Name) \ 4471cb0ef41Sopenharmony_ci case IrOpcode::k##Name: { \ 4481cb0ef41Sopenharmony_ci new_type = Type::Intersect(op_typer_.Name(input0_type), \ 4491cb0ef41Sopenharmony_ci info->restriction_type(), graph_zone()); \ 4501cb0ef41Sopenharmony_ci break; \ 4511cb0ef41Sopenharmony_ci } 4521cb0ef41Sopenharmony_ci SIMPLIFIED_SPECULATIVE_NUMBER_UNOP_LIST(DECLARE_CASE) 4531cb0ef41Sopenharmony_ci#undef DECLARE_CASE 4541cb0ef41Sopenharmony_ci 4551cb0ef41Sopenharmony_ci case IrOpcode::kConvertReceiver: 4561cb0ef41Sopenharmony_ci new_type = op_typer_.ConvertReceiver(input0_type); 4571cb0ef41Sopenharmony_ci break; 4581cb0ef41Sopenharmony_ci 4591cb0ef41Sopenharmony_ci case IrOpcode::kPlainPrimitiveToNumber: 4601cb0ef41Sopenharmony_ci new_type = op_typer_.ToNumber(input0_type); 4611cb0ef41Sopenharmony_ci break; 4621cb0ef41Sopenharmony_ci 4631cb0ef41Sopenharmony_ci case IrOpcode::kCheckBounds: 4641cb0ef41Sopenharmony_ci new_type = 4651cb0ef41Sopenharmony_ci Type::Intersect(op_typer_.CheckBounds(input0_type, input1_type), 4661cb0ef41Sopenharmony_ci info->restriction_type(), graph_zone()); 4671cb0ef41Sopenharmony_ci break; 4681cb0ef41Sopenharmony_ci 4691cb0ef41Sopenharmony_ci case IrOpcode::kCheckFloat64Hole: 4701cb0ef41Sopenharmony_ci new_type = Type::Intersect(op_typer_.CheckFloat64Hole(input0_type), 4711cb0ef41Sopenharmony_ci info->restriction_type(), graph_zone()); 4721cb0ef41Sopenharmony_ci break; 4731cb0ef41Sopenharmony_ci 4741cb0ef41Sopenharmony_ci case IrOpcode::kCheckNumber: 4751cb0ef41Sopenharmony_ci new_type = Type::Intersect(op_typer_.CheckNumber(input0_type), 4761cb0ef41Sopenharmony_ci info->restriction_type(), graph_zone()); 4771cb0ef41Sopenharmony_ci break; 4781cb0ef41Sopenharmony_ci 4791cb0ef41Sopenharmony_ci case IrOpcode::kPhi: { 4801cb0ef41Sopenharmony_ci new_type = TypePhi(node); 4811cb0ef41Sopenharmony_ci if (!type.IsInvalid()) { 4821cb0ef41Sopenharmony_ci new_type = Weaken(node, type, new_type); 4831cb0ef41Sopenharmony_ci } 4841cb0ef41Sopenharmony_ci break; 4851cb0ef41Sopenharmony_ci } 4861cb0ef41Sopenharmony_ci 4871cb0ef41Sopenharmony_ci case IrOpcode::kConvertTaggedHoleToUndefined: 4881cb0ef41Sopenharmony_ci new_type = op_typer_.ConvertTaggedHoleToUndefined( 4891cb0ef41Sopenharmony_ci FeedbackTypeOf(node->InputAt(0))); 4901cb0ef41Sopenharmony_ci break; 4911cb0ef41Sopenharmony_ci 4921cb0ef41Sopenharmony_ci case IrOpcode::kTypeGuard: { 4931cb0ef41Sopenharmony_ci new_type = op_typer_.TypeTypeGuard(node->op(), 4941cb0ef41Sopenharmony_ci FeedbackTypeOf(node->InputAt(0))); 4951cb0ef41Sopenharmony_ci break; 4961cb0ef41Sopenharmony_ci } 4971cb0ef41Sopenharmony_ci 4981cb0ef41Sopenharmony_ci case IrOpcode::kSelect: { 4991cb0ef41Sopenharmony_ci new_type = TypeSelect(node); 5001cb0ef41Sopenharmony_ci break; 5011cb0ef41Sopenharmony_ci } 5021cb0ef41Sopenharmony_ci 5031cb0ef41Sopenharmony_ci default: 5041cb0ef41Sopenharmony_ci // Shortcut for operations that we do not handle. 5051cb0ef41Sopenharmony_ci if (type.IsInvalid()) { 5061cb0ef41Sopenharmony_ci GetInfo(node)->set_feedback_type(NodeProperties::GetType(node)); 5071cb0ef41Sopenharmony_ci return true; 5081cb0ef41Sopenharmony_ci } 5091cb0ef41Sopenharmony_ci return false; 5101cb0ef41Sopenharmony_ci } 5111cb0ef41Sopenharmony_ci // We need to guarantee that the feedback type is a subtype of the upper 5121cb0ef41Sopenharmony_ci // bound. Naively that should hold, but weakening can actually produce 5131cb0ef41Sopenharmony_ci // a bigger type if we are unlucky with ordering of phi typing. To be 5141cb0ef41Sopenharmony_ci // really sure, just intersect the upper bound with the feedback type. 5151cb0ef41Sopenharmony_ci new_type = Type::Intersect(GetUpperBound(node), new_type, graph_zone()); 5161cb0ef41Sopenharmony_ci 5171cb0ef41Sopenharmony_ci if (!type.IsInvalid() && new_type.Is(type)) return false; 5181cb0ef41Sopenharmony_ci GetInfo(node)->set_feedback_type(new_type); 5191cb0ef41Sopenharmony_ci if (FLAG_trace_representation) { 5201cb0ef41Sopenharmony_ci PrintNodeFeedbackType(node); 5211cb0ef41Sopenharmony_ci } 5221cb0ef41Sopenharmony_ci return true; 5231cb0ef41Sopenharmony_ci } 5241cb0ef41Sopenharmony_ci 5251cb0ef41Sopenharmony_ci void PrintNodeFeedbackType(Node* n) { 5261cb0ef41Sopenharmony_ci StdoutStream os; 5271cb0ef41Sopenharmony_ci os << "#" << n->id() << ":" << *n->op() << "("; 5281cb0ef41Sopenharmony_ci int j = 0; 5291cb0ef41Sopenharmony_ci for (Node* const i : n->inputs()) { 5301cb0ef41Sopenharmony_ci if (j++ > 0) os << ", "; 5311cb0ef41Sopenharmony_ci os << "#" << i->id() << ":" << i->op()->mnemonic(); 5321cb0ef41Sopenharmony_ci } 5331cb0ef41Sopenharmony_ci os << ")"; 5341cb0ef41Sopenharmony_ci if (NodeProperties::IsTyped(n)) { 5351cb0ef41Sopenharmony_ci Type static_type = NodeProperties::GetType(n); 5361cb0ef41Sopenharmony_ci os << " [Static type: " << static_type; 5371cb0ef41Sopenharmony_ci Type feedback_type = GetInfo(n)->feedback_type(); 5381cb0ef41Sopenharmony_ci if (!feedback_type.IsInvalid() && feedback_type != static_type) { 5391cb0ef41Sopenharmony_ci os << ", Feedback type: " << feedback_type; 5401cb0ef41Sopenharmony_ci } 5411cb0ef41Sopenharmony_ci os << "]"; 5421cb0ef41Sopenharmony_ci } 5431cb0ef41Sopenharmony_ci os << std::endl; 5441cb0ef41Sopenharmony_ci } 5451cb0ef41Sopenharmony_ci 5461cb0ef41Sopenharmony_ci Type Weaken(Node* node, Type previous_type, Type current_type) { 5471cb0ef41Sopenharmony_ci // If the types have nothing to do with integers, return the types. 5481cb0ef41Sopenharmony_ci Type const integer = type_cache_->kInteger; 5491cb0ef41Sopenharmony_ci if (!previous_type.Maybe(integer)) { 5501cb0ef41Sopenharmony_ci return current_type; 5511cb0ef41Sopenharmony_ci } 5521cb0ef41Sopenharmony_ci DCHECK(current_type.Maybe(integer)); 5531cb0ef41Sopenharmony_ci 5541cb0ef41Sopenharmony_ci Type current_integer = Type::Intersect(current_type, integer, graph_zone()); 5551cb0ef41Sopenharmony_ci DCHECK(!current_integer.IsNone()); 5561cb0ef41Sopenharmony_ci Type previous_integer = 5571cb0ef41Sopenharmony_ci Type::Intersect(previous_type, integer, graph_zone()); 5581cb0ef41Sopenharmony_ci DCHECK(!previous_integer.IsNone()); 5591cb0ef41Sopenharmony_ci 5601cb0ef41Sopenharmony_ci // Once we start weakening a node, we should always weaken. 5611cb0ef41Sopenharmony_ci if (!GetInfo(node)->weakened()) { 5621cb0ef41Sopenharmony_ci // Only weaken if there is range involved; we should converge quickly 5631cb0ef41Sopenharmony_ci // for all other types (the exception is a union of many constants, 5641cb0ef41Sopenharmony_ci // but we currently do not increase the number of constants in unions). 5651cb0ef41Sopenharmony_ci Type previous = previous_integer.GetRange(); 5661cb0ef41Sopenharmony_ci Type current = current_integer.GetRange(); 5671cb0ef41Sopenharmony_ci if (current.IsInvalid() || previous.IsInvalid()) { 5681cb0ef41Sopenharmony_ci return current_type; 5691cb0ef41Sopenharmony_ci } 5701cb0ef41Sopenharmony_ci // Range is involved => we are weakening. 5711cb0ef41Sopenharmony_ci GetInfo(node)->set_weakened(); 5721cb0ef41Sopenharmony_ci } 5731cb0ef41Sopenharmony_ci 5741cb0ef41Sopenharmony_ci return Type::Union(current_type, 5751cb0ef41Sopenharmony_ci op_typer_.WeakenRange(previous_integer, current_integer), 5761cb0ef41Sopenharmony_ci graph_zone()); 5771cb0ef41Sopenharmony_ci } 5781cb0ef41Sopenharmony_ci 5791cb0ef41Sopenharmony_ci // Generates a pre-order traversal of the nodes, starting with End. 5801cb0ef41Sopenharmony_ci void GenerateTraversal() { 5811cb0ef41Sopenharmony_ci // Reset previous state. 5821cb0ef41Sopenharmony_ci ResetNodeInfoState(); 5831cb0ef41Sopenharmony_ci traversal_nodes_.clear(); 5841cb0ef41Sopenharmony_ci count_ = graph()->NodeCount(); 5851cb0ef41Sopenharmony_ci info_.resize(count_); 5861cb0ef41Sopenharmony_ci 5871cb0ef41Sopenharmony_ci ZoneStack<NodeState> stack(zone_); 5881cb0ef41Sopenharmony_ci 5891cb0ef41Sopenharmony_ci stack.push({graph()->end(), 0}); 5901cb0ef41Sopenharmony_ci GetInfo(graph()->end())->set_pushed(); 5911cb0ef41Sopenharmony_ci while (!stack.empty()) { 5921cb0ef41Sopenharmony_ci NodeState& current = stack.top(); 5931cb0ef41Sopenharmony_ci Node* node = current.node; 5941cb0ef41Sopenharmony_ci 5951cb0ef41Sopenharmony_ci // If there is an unvisited input, push it and continue with that node. 5961cb0ef41Sopenharmony_ci bool pushed_unvisited = false; 5971cb0ef41Sopenharmony_ci while (current.input_index < node->InputCount()) { 5981cb0ef41Sopenharmony_ci Node* input = node->InputAt(current.input_index); 5991cb0ef41Sopenharmony_ci NodeInfo* input_info = GetInfo(input); 6001cb0ef41Sopenharmony_ci current.input_index++; 6011cb0ef41Sopenharmony_ci if (input_info->unvisited()) { 6021cb0ef41Sopenharmony_ci input_info->set_pushed(); 6031cb0ef41Sopenharmony_ci stack.push({input, 0}); 6041cb0ef41Sopenharmony_ci pushed_unvisited = true; 6051cb0ef41Sopenharmony_ci break; 6061cb0ef41Sopenharmony_ci } else if (input_info->pushed()) { 6071cb0ef41Sopenharmony_ci // Optimization for the Retype phase. 6081cb0ef41Sopenharmony_ci // If we had already pushed (and not visited) an input, it means that 6091cb0ef41Sopenharmony_ci // the current node will be visited in the Retype phase before one of 6101cb0ef41Sopenharmony_ci // its inputs. If this happens, the current node might need to be 6111cb0ef41Sopenharmony_ci // revisited. 6121cb0ef41Sopenharmony_ci MarkAsPossibleRevisit(node, input); 6131cb0ef41Sopenharmony_ci } 6141cb0ef41Sopenharmony_ci } 6151cb0ef41Sopenharmony_ci 6161cb0ef41Sopenharmony_ci if (pushed_unvisited) continue; 6171cb0ef41Sopenharmony_ci 6181cb0ef41Sopenharmony_ci stack.pop(); 6191cb0ef41Sopenharmony_ci NodeInfo* info = GetInfo(node); 6201cb0ef41Sopenharmony_ci info->set_visited(); 6211cb0ef41Sopenharmony_ci 6221cb0ef41Sopenharmony_ci // Generate the traversal 6231cb0ef41Sopenharmony_ci traversal_nodes_.push_back(node); 6241cb0ef41Sopenharmony_ci } 6251cb0ef41Sopenharmony_ci } 6261cb0ef41Sopenharmony_ci 6271cb0ef41Sopenharmony_ci void PushNodeToRevisitIfVisited(Node* node) { 6281cb0ef41Sopenharmony_ci NodeInfo* info = GetInfo(node); 6291cb0ef41Sopenharmony_ci if (info->visited()) { 6301cb0ef41Sopenharmony_ci TRACE(" QUEUEING #%d: %s\n", node->id(), node->op()->mnemonic()); 6311cb0ef41Sopenharmony_ci info->set_queued(); 6321cb0ef41Sopenharmony_ci revisit_queue_.push(node); 6331cb0ef41Sopenharmony_ci } 6341cb0ef41Sopenharmony_ci } 6351cb0ef41Sopenharmony_ci 6361cb0ef41Sopenharmony_ci // Tries to update the feedback type of the node, as well as setting its 6371cb0ef41Sopenharmony_ci // machine representation (in VisitNode). Returns true iff updating the 6381cb0ef41Sopenharmony_ci // feedback type is successful. 6391cb0ef41Sopenharmony_ci bool RetypeNode(Node* node) { 6401cb0ef41Sopenharmony_ci NodeInfo* info = GetInfo(node); 6411cb0ef41Sopenharmony_ci info->set_visited(); 6421cb0ef41Sopenharmony_ci bool updated = UpdateFeedbackType(node); 6431cb0ef41Sopenharmony_ci TRACE(" visit #%d: %s\n", node->id(), node->op()->mnemonic()); 6441cb0ef41Sopenharmony_ci VisitNode<RETYPE>(node, info->truncation(), nullptr); 6451cb0ef41Sopenharmony_ci TRACE(" ==> output %s\n", MachineReprToString(info->representation())); 6461cb0ef41Sopenharmony_ci return updated; 6471cb0ef41Sopenharmony_ci } 6481cb0ef41Sopenharmony_ci 6491cb0ef41Sopenharmony_ci // Visits the node and marks it as visited. Inside of VisitNode, we might 6501cb0ef41Sopenharmony_ci // change the truncation of one of our inputs (see EnqueueInput<PROPAGATE> for 6511cb0ef41Sopenharmony_ci // this). If we change the truncation of an already visited node, we will add 6521cb0ef41Sopenharmony_ci // it to the revisit queue. 6531cb0ef41Sopenharmony_ci void PropagateTruncation(Node* node) { 6541cb0ef41Sopenharmony_ci NodeInfo* info = GetInfo(node); 6551cb0ef41Sopenharmony_ci info->set_visited(); 6561cb0ef41Sopenharmony_ci TRACE(" visit #%d: %s (trunc: %s)\n", node->id(), node->op()->mnemonic(), 6571cb0ef41Sopenharmony_ci info->truncation().description()); 6581cb0ef41Sopenharmony_ci VisitNode<PROPAGATE>(node, info->truncation(), nullptr); 6591cb0ef41Sopenharmony_ci } 6601cb0ef41Sopenharmony_ci 6611cb0ef41Sopenharmony_ci // Backward propagation of truncations to a fixpoint. 6621cb0ef41Sopenharmony_ci void RunPropagatePhase() { 6631cb0ef41Sopenharmony_ci TRACE("--{Propagate phase}--\n"); 6641cb0ef41Sopenharmony_ci ResetNodeInfoState(); 6651cb0ef41Sopenharmony_ci DCHECK(revisit_queue_.empty()); 6661cb0ef41Sopenharmony_ci 6671cb0ef41Sopenharmony_ci // Process nodes in reverse post order, with End as the root. 6681cb0ef41Sopenharmony_ci for (auto it = traversal_nodes_.crbegin(); it != traversal_nodes_.crend(); 6691cb0ef41Sopenharmony_ci ++it) { 6701cb0ef41Sopenharmony_ci PropagateTruncation(*it); 6711cb0ef41Sopenharmony_ci 6721cb0ef41Sopenharmony_ci while (!revisit_queue_.empty()) { 6731cb0ef41Sopenharmony_ci Node* node = revisit_queue_.front(); 6741cb0ef41Sopenharmony_ci revisit_queue_.pop(); 6751cb0ef41Sopenharmony_ci PropagateTruncation(node); 6761cb0ef41Sopenharmony_ci } 6771cb0ef41Sopenharmony_ci } 6781cb0ef41Sopenharmony_ci } 6791cb0ef41Sopenharmony_ci 6801cb0ef41Sopenharmony_ci // Forward propagation of types from type feedback to a fixpoint. 6811cb0ef41Sopenharmony_ci void RunRetypePhase() { 6821cb0ef41Sopenharmony_ci TRACE("--{Retype phase}--\n"); 6831cb0ef41Sopenharmony_ci ResetNodeInfoState(); 6841cb0ef41Sopenharmony_ci DCHECK(revisit_queue_.empty()); 6851cb0ef41Sopenharmony_ci 6861cb0ef41Sopenharmony_ci for (auto it = traversal_nodes_.cbegin(); it != traversal_nodes_.cend(); 6871cb0ef41Sopenharmony_ci ++it) { 6881cb0ef41Sopenharmony_ci Node* node = *it; 6891cb0ef41Sopenharmony_ci if (!RetypeNode(node)) continue; 6901cb0ef41Sopenharmony_ci 6911cb0ef41Sopenharmony_ci auto revisit_it = might_need_revisit_.find(node); 6921cb0ef41Sopenharmony_ci if (revisit_it == might_need_revisit_.end()) continue; 6931cb0ef41Sopenharmony_ci 6941cb0ef41Sopenharmony_ci for (Node* const user : revisit_it->second) { 6951cb0ef41Sopenharmony_ci PushNodeToRevisitIfVisited(user); 6961cb0ef41Sopenharmony_ci } 6971cb0ef41Sopenharmony_ci 6981cb0ef41Sopenharmony_ci // Process the revisit queue. 6991cb0ef41Sopenharmony_ci while (!revisit_queue_.empty()) { 7001cb0ef41Sopenharmony_ci Node* revisit_node = revisit_queue_.front(); 7011cb0ef41Sopenharmony_ci revisit_queue_.pop(); 7021cb0ef41Sopenharmony_ci if (!RetypeNode(revisit_node)) continue; 7031cb0ef41Sopenharmony_ci // Here we need to check all uses since we can't easily know which 7041cb0ef41Sopenharmony_ci // nodes will need to be revisited due to having an input which was 7051cb0ef41Sopenharmony_ci // a revisited node. 7061cb0ef41Sopenharmony_ci for (Node* const user : revisit_node->uses()) { 7071cb0ef41Sopenharmony_ci PushNodeToRevisitIfVisited(user); 7081cb0ef41Sopenharmony_ci } 7091cb0ef41Sopenharmony_ci } 7101cb0ef41Sopenharmony_ci } 7111cb0ef41Sopenharmony_ci } 7121cb0ef41Sopenharmony_ci 7131cb0ef41Sopenharmony_ci // Lowering and change insertion phase. 7141cb0ef41Sopenharmony_ci void RunLowerPhase(SimplifiedLowering* lowering) { 7151cb0ef41Sopenharmony_ci TRACE("--{Lower phase}--\n"); 7161cb0ef41Sopenharmony_ci for (auto it = traversal_nodes_.cbegin(); it != traversal_nodes_.cend(); 7171cb0ef41Sopenharmony_ci ++it) { 7181cb0ef41Sopenharmony_ci Node* node = *it; 7191cb0ef41Sopenharmony_ci NodeInfo* info = GetInfo(node); 7201cb0ef41Sopenharmony_ci TRACE(" visit #%d: %s\n", node->id(), node->op()->mnemonic()); 7211cb0ef41Sopenharmony_ci // Reuse {VisitNode()} so the representation rules are in one place. 7221cb0ef41Sopenharmony_ci SourcePositionTable::Scope scope( 7231cb0ef41Sopenharmony_ci source_positions_, source_positions_->GetSourcePosition(node)); 7241cb0ef41Sopenharmony_ci NodeOriginTable::Scope origin_scope(node_origins_, "simplified lowering", 7251cb0ef41Sopenharmony_ci node); 7261cb0ef41Sopenharmony_ci VisitNode<LOWER>(node, info->truncation(), lowering); 7271cb0ef41Sopenharmony_ci } 7281cb0ef41Sopenharmony_ci 7291cb0ef41Sopenharmony_ci // Perform the final replacements. 7301cb0ef41Sopenharmony_ci for (NodeVector::iterator i = replacements_.begin(); 7311cb0ef41Sopenharmony_ci i != replacements_.end(); ++i) { 7321cb0ef41Sopenharmony_ci Node* node = *i; 7331cb0ef41Sopenharmony_ci Node* replacement = *(++i); 7341cb0ef41Sopenharmony_ci node->ReplaceUses(replacement); 7351cb0ef41Sopenharmony_ci node->Kill(); 7361cb0ef41Sopenharmony_ci // We also need to replace the node in the rest of the vector. 7371cb0ef41Sopenharmony_ci for (NodeVector::iterator j = i + 1; j != replacements_.end(); ++j) { 7381cb0ef41Sopenharmony_ci ++j; 7391cb0ef41Sopenharmony_ci if (*j == node) *j = replacement; 7401cb0ef41Sopenharmony_ci } 7411cb0ef41Sopenharmony_ci } 7421cb0ef41Sopenharmony_ci } 7431cb0ef41Sopenharmony_ci 7441cb0ef41Sopenharmony_ci void RunVerifyPhase(OptimizedCompilationInfo* info) { 7451cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(verifier_); 7461cb0ef41Sopenharmony_ci 7471cb0ef41Sopenharmony_ci TRACE("--{Verify Phase}--\n"); 7481cb0ef41Sopenharmony_ci 7491cb0ef41Sopenharmony_ci // Generate a new traversal containing all the new nodes created during 7501cb0ef41Sopenharmony_ci // lowering. 7511cb0ef41Sopenharmony_ci GenerateTraversal(); 7521cb0ef41Sopenharmony_ci 7531cb0ef41Sopenharmony_ci // Set node types to the refined types computed during retyping. 7541cb0ef41Sopenharmony_ci for (Node* node : traversal_nodes_) { 7551cb0ef41Sopenharmony_ci NodeInfo* info = GetInfo(node); 7561cb0ef41Sopenharmony_ci if (!info->feedback_type().IsInvalid()) { 7571cb0ef41Sopenharmony_ci NodeProperties::SetType(node, info->feedback_type()); 7581cb0ef41Sopenharmony_ci } 7591cb0ef41Sopenharmony_ci } 7601cb0ef41Sopenharmony_ci 7611cb0ef41Sopenharmony_ci // Verify all nodes. 7621cb0ef41Sopenharmony_ci for (Node* node : traversal_nodes_) verifier_->VisitNode(node, op_typer_); 7631cb0ef41Sopenharmony_ci 7641cb0ef41Sopenharmony_ci // Print graph. 7651cb0ef41Sopenharmony_ci if (info != nullptr && info->trace_turbo_json()) { 7661cb0ef41Sopenharmony_ci UnparkedScopeIfNeeded scope(broker_); 7671cb0ef41Sopenharmony_ci AllowHandleDereference allow_deref; 7681cb0ef41Sopenharmony_ci 7691cb0ef41Sopenharmony_ci TurboJsonFile json_of(info, std::ios_base::app); 7701cb0ef41Sopenharmony_ci JSONGraphWriterWithVerifierTypes writer( 7711cb0ef41Sopenharmony_ci json_of, graph(), source_positions_, node_origins_, verifier_); 7721cb0ef41Sopenharmony_ci writer.PrintPhase("V8.TFSimplifiedLoweringVerifier"); 7731cb0ef41Sopenharmony_ci } 7741cb0ef41Sopenharmony_ci 7751cb0ef41Sopenharmony_ci // Eliminate all introduced hints. 7761cb0ef41Sopenharmony_ci for (Node* node : verifier_->inserted_hints()) { 7771cb0ef41Sopenharmony_ci Node* input = node->InputAt(0); 7781cb0ef41Sopenharmony_ci node->ReplaceUses(input); 7791cb0ef41Sopenharmony_ci node->Kill(); 7801cb0ef41Sopenharmony_ci } 7811cb0ef41Sopenharmony_ci } 7821cb0ef41Sopenharmony_ci 7831cb0ef41Sopenharmony_ci void Run(SimplifiedLowering* lowering) { 7841cb0ef41Sopenharmony_ci GenerateTraversal(); 7851cb0ef41Sopenharmony_ci RunPropagatePhase(); 7861cb0ef41Sopenharmony_ci RunRetypePhase(); 7871cb0ef41Sopenharmony_ci RunLowerPhase(lowering); 7881cb0ef41Sopenharmony_ci 7891cb0ef41Sopenharmony_ci if (verification_enabled()) { 7901cb0ef41Sopenharmony_ci RunVerifyPhase(lowering->info_); 7911cb0ef41Sopenharmony_ci } 7921cb0ef41Sopenharmony_ci } 7931cb0ef41Sopenharmony_ci 7941cb0ef41Sopenharmony_ci // Just assert for Retype and Lower. Propagate specialized below. 7951cb0ef41Sopenharmony_ci template <Phase T> 7961cb0ef41Sopenharmony_ci void EnqueueInput(Node* use_node, int index, 7971cb0ef41Sopenharmony_ci UseInfo use_info = UseInfo::None()) { 7981cb0ef41Sopenharmony_ci static_assert(retype<T>() || lower<T>(), 7991cb0ef41Sopenharmony_ci "This version of EnqueueInput has to be called in " 8001cb0ef41Sopenharmony_ci "the Retype or Lower phase."); 8011cb0ef41Sopenharmony_ci } 8021cb0ef41Sopenharmony_ci 8031cb0ef41Sopenharmony_ci template <Phase T> 8041cb0ef41Sopenharmony_ci static constexpr bool propagate() { 8051cb0ef41Sopenharmony_ci return T == PROPAGATE; 8061cb0ef41Sopenharmony_ci } 8071cb0ef41Sopenharmony_ci 8081cb0ef41Sopenharmony_ci template <Phase T> 8091cb0ef41Sopenharmony_ci static constexpr bool retype() { 8101cb0ef41Sopenharmony_ci return T == RETYPE; 8111cb0ef41Sopenharmony_ci } 8121cb0ef41Sopenharmony_ci 8131cb0ef41Sopenharmony_ci template <Phase T> 8141cb0ef41Sopenharmony_ci static constexpr bool lower() { 8151cb0ef41Sopenharmony_ci return T == LOWER; 8161cb0ef41Sopenharmony_ci } 8171cb0ef41Sopenharmony_ci 8181cb0ef41Sopenharmony_ci template <Phase T> 8191cb0ef41Sopenharmony_ci void SetOutput(Node* node, MachineRepresentation representation, 8201cb0ef41Sopenharmony_ci Type restriction_type = Type::Any()); 8211cb0ef41Sopenharmony_ci 8221cb0ef41Sopenharmony_ci Type GetUpperBound(Node* node) { return NodeProperties::GetType(node); } 8231cb0ef41Sopenharmony_ci 8241cb0ef41Sopenharmony_ci bool InputCannotBe(Node* node, Type type) { 8251cb0ef41Sopenharmony_ci DCHECK_EQ(1, node->op()->ValueInputCount()); 8261cb0ef41Sopenharmony_ci return !GetUpperBound(node->InputAt(0)).Maybe(type); 8271cb0ef41Sopenharmony_ci } 8281cb0ef41Sopenharmony_ci 8291cb0ef41Sopenharmony_ci bool InputIs(Node* node, Type type) { 8301cb0ef41Sopenharmony_ci DCHECK_EQ(1, node->op()->ValueInputCount()); 8311cb0ef41Sopenharmony_ci return GetUpperBound(node->InputAt(0)).Is(type); 8321cb0ef41Sopenharmony_ci } 8331cb0ef41Sopenharmony_ci 8341cb0ef41Sopenharmony_ci bool BothInputsAreSigned32(Node* node) { 8351cb0ef41Sopenharmony_ci return BothInputsAre(node, Type::Signed32()); 8361cb0ef41Sopenharmony_ci } 8371cb0ef41Sopenharmony_ci 8381cb0ef41Sopenharmony_ci bool BothInputsAreUnsigned32(Node* node) { 8391cb0ef41Sopenharmony_ci return BothInputsAre(node, Type::Unsigned32()); 8401cb0ef41Sopenharmony_ci } 8411cb0ef41Sopenharmony_ci 8421cb0ef41Sopenharmony_ci bool BothInputsAre(Node* node, Type type) { 8431cb0ef41Sopenharmony_ci DCHECK_EQ(2, node->op()->ValueInputCount()); 8441cb0ef41Sopenharmony_ci return GetUpperBound(node->InputAt(0)).Is(type) && 8451cb0ef41Sopenharmony_ci GetUpperBound(node->InputAt(1)).Is(type); 8461cb0ef41Sopenharmony_ci } 8471cb0ef41Sopenharmony_ci 8481cb0ef41Sopenharmony_ci bool IsNodeRepresentationTagged(Node* node) { 8491cb0ef41Sopenharmony_ci MachineRepresentation representation = GetInfo(node)->representation(); 8501cb0ef41Sopenharmony_ci return IsAnyTagged(representation); 8511cb0ef41Sopenharmony_ci } 8521cb0ef41Sopenharmony_ci 8531cb0ef41Sopenharmony_ci bool OneInputCannotBe(Node* node, Type type) { 8541cb0ef41Sopenharmony_ci DCHECK_EQ(2, node->op()->ValueInputCount()); 8551cb0ef41Sopenharmony_ci return !GetUpperBound(node->InputAt(0)).Maybe(type) || 8561cb0ef41Sopenharmony_ci !GetUpperBound(node->InputAt(1)).Maybe(type); 8571cb0ef41Sopenharmony_ci } 8581cb0ef41Sopenharmony_ci 8591cb0ef41Sopenharmony_ci void ChangeToDeadValue(Node* node, Node* effect, Node* control) { 8601cb0ef41Sopenharmony_ci DCHECK(TypeOf(node).IsNone()); 8611cb0ef41Sopenharmony_ci // If the node is unreachable, insert an Unreachable node and mark the 8621cb0ef41Sopenharmony_ci // value dead. 8631cb0ef41Sopenharmony_ci // TODO(jarin,turbofan) Find a way to unify/merge this insertion with 8641cb0ef41Sopenharmony_ci // InsertUnreachableIfNecessary. 8651cb0ef41Sopenharmony_ci Node* unreachable = effect = 8661cb0ef41Sopenharmony_ci graph()->NewNode(common()->Unreachable(), effect, control); 8671cb0ef41Sopenharmony_ci const Operator* dead_value = 8681cb0ef41Sopenharmony_ci common()->DeadValue(GetInfo(node)->representation()); 8691cb0ef41Sopenharmony_ci node->ReplaceInput(0, unreachable); 8701cb0ef41Sopenharmony_ci node->TrimInputCount(dead_value->ValueInputCount()); 8711cb0ef41Sopenharmony_ci ReplaceEffectControlUses(node, effect, control); 8721cb0ef41Sopenharmony_ci ChangeOp(node, dead_value); 8731cb0ef41Sopenharmony_ci } 8741cb0ef41Sopenharmony_ci 8751cb0ef41Sopenharmony_ci // This function is a generalization of ChangeToPureOp. It can be used to 8761cb0ef41Sopenharmony_ci // replace a node that is part of the effect and control chain by a pure node. 8771cb0ef41Sopenharmony_ci void ReplaceWithPureNode(Node* node, Node* pure_node) { 8781cb0ef41Sopenharmony_ci DCHECK(pure_node->op()->HasProperty(Operator::kPure)); 8791cb0ef41Sopenharmony_ci if (node->op()->EffectInputCount() > 0) { 8801cb0ef41Sopenharmony_ci DCHECK_LT(0, node->op()->ControlInputCount()); 8811cb0ef41Sopenharmony_ci Node* control = NodeProperties::GetControlInput(node); 8821cb0ef41Sopenharmony_ci Node* effect = NodeProperties::GetEffectInput(node); 8831cb0ef41Sopenharmony_ci if (TypeOf(node).IsNone()) { 8841cb0ef41Sopenharmony_ci ChangeToDeadValue(node, effect, control); 8851cb0ef41Sopenharmony_ci return; 8861cb0ef41Sopenharmony_ci } 8871cb0ef41Sopenharmony_ci // Rewire the effect and control chains. 8881cb0ef41Sopenharmony_ci ReplaceEffectControlUses(node, effect, control); 8891cb0ef41Sopenharmony_ci } else { 8901cb0ef41Sopenharmony_ci DCHECK_EQ(0, node->op()->ControlInputCount()); 8911cb0ef41Sopenharmony_ci } 8921cb0ef41Sopenharmony_ci DeferReplacement(node, pure_node); 8931cb0ef41Sopenharmony_ci } 8941cb0ef41Sopenharmony_ci 8951cb0ef41Sopenharmony_ci void ChangeToPureOp(Node* node, const Operator* new_op) { 8961cb0ef41Sopenharmony_ci DCHECK(new_op->HasProperty(Operator::kPure)); 8971cb0ef41Sopenharmony_ci DCHECK_EQ(new_op->ValueInputCount(), node->op()->ValueInputCount()); 8981cb0ef41Sopenharmony_ci if (node->op()->EffectInputCount() > 0) { 8991cb0ef41Sopenharmony_ci DCHECK_LT(0, node->op()->ControlInputCount()); 9001cb0ef41Sopenharmony_ci Node* control = NodeProperties::GetControlInput(node); 9011cb0ef41Sopenharmony_ci Node* effect = NodeProperties::GetEffectInput(node); 9021cb0ef41Sopenharmony_ci if (TypeOf(node).IsNone()) { 9031cb0ef41Sopenharmony_ci ChangeToDeadValue(node, effect, control); 9041cb0ef41Sopenharmony_ci return; 9051cb0ef41Sopenharmony_ci } 9061cb0ef41Sopenharmony_ci // Rewire the effect and control chains. 9071cb0ef41Sopenharmony_ci node->TrimInputCount(new_op->ValueInputCount()); 9081cb0ef41Sopenharmony_ci ReplaceEffectControlUses(node, effect, control); 9091cb0ef41Sopenharmony_ci } else { 9101cb0ef41Sopenharmony_ci DCHECK_EQ(0, node->op()->ControlInputCount()); 9111cb0ef41Sopenharmony_ci } 9121cb0ef41Sopenharmony_ci ChangeOp(node, new_op); 9131cb0ef41Sopenharmony_ci } 9141cb0ef41Sopenharmony_ci 9151cb0ef41Sopenharmony_ci void ChangeUnaryToPureBinaryOp(Node* node, const Operator* new_op, 9161cb0ef41Sopenharmony_ci int new_input_index, Node* new_input) { 9171cb0ef41Sopenharmony_ci DCHECK(new_op->HasProperty(Operator::kPure)); 9181cb0ef41Sopenharmony_ci DCHECK_EQ(new_op->ValueInputCount(), 2); 9191cb0ef41Sopenharmony_ci DCHECK_EQ(node->op()->ValueInputCount(), 1); 9201cb0ef41Sopenharmony_ci DCHECK_LE(0, new_input_index); 9211cb0ef41Sopenharmony_ci DCHECK_LE(new_input_index, 1); 9221cb0ef41Sopenharmony_ci if (node->op()->EffectInputCount() > 0) { 9231cb0ef41Sopenharmony_ci DCHECK_LT(0, node->op()->ControlInputCount()); 9241cb0ef41Sopenharmony_ci Node* control = NodeProperties::GetControlInput(node); 9251cb0ef41Sopenharmony_ci Node* effect = NodeProperties::GetEffectInput(node); 9261cb0ef41Sopenharmony_ci if (TypeOf(node).IsNone()) { 9271cb0ef41Sopenharmony_ci ChangeToDeadValue(node, effect, control); 9281cb0ef41Sopenharmony_ci return; 9291cb0ef41Sopenharmony_ci } 9301cb0ef41Sopenharmony_ci node->TrimInputCount(node->op()->ValueInputCount()); 9311cb0ef41Sopenharmony_ci ReplaceEffectControlUses(node, effect, control); 9321cb0ef41Sopenharmony_ci } else { 9331cb0ef41Sopenharmony_ci DCHECK_EQ(0, node->op()->ControlInputCount()); 9341cb0ef41Sopenharmony_ci } 9351cb0ef41Sopenharmony_ci if (new_input_index == 0) { 9361cb0ef41Sopenharmony_ci node->InsertInput(jsgraph_->zone(), 0, new_input); 9371cb0ef41Sopenharmony_ci } else { 9381cb0ef41Sopenharmony_ci DCHECK_EQ(new_input_index, 1); 9391cb0ef41Sopenharmony_ci DCHECK_EQ(node->InputCount(), 1); 9401cb0ef41Sopenharmony_ci node->AppendInput(jsgraph_->zone(), new_input); 9411cb0ef41Sopenharmony_ci } 9421cb0ef41Sopenharmony_ci ChangeOp(node, new_op); 9431cb0ef41Sopenharmony_ci } 9441cb0ef41Sopenharmony_ci 9451cb0ef41Sopenharmony_ci // Converts input {index} of {node} according to given UseInfo {use}, 9461cb0ef41Sopenharmony_ci // assuming the type of the input is {input_type}. If {input_type} is null, 9471cb0ef41Sopenharmony_ci // it takes the input from the input node {TypeOf(node->InputAt(index))}. 9481cb0ef41Sopenharmony_ci void ConvertInput(Node* node, int index, UseInfo use, 9491cb0ef41Sopenharmony_ci Type input_type = Type::Invalid()) { 9501cb0ef41Sopenharmony_ci // In the change phase, insert a change before the use if necessary. 9511cb0ef41Sopenharmony_ci if (use.representation() == MachineRepresentation::kNone) 9521cb0ef41Sopenharmony_ci return; // No input requirement on the use. 9531cb0ef41Sopenharmony_ci Node* input = node->InputAt(index); 9541cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(input); 9551cb0ef41Sopenharmony_ci NodeInfo* input_info = GetInfo(input); 9561cb0ef41Sopenharmony_ci MachineRepresentation input_rep = input_info->representation(); 9571cb0ef41Sopenharmony_ci if (input_rep != use.representation() || 9581cb0ef41Sopenharmony_ci use.type_check() != TypeCheckKind::kNone) { 9591cb0ef41Sopenharmony_ci // Output representation doesn't match usage. 9601cb0ef41Sopenharmony_ci TRACE(" change: #%d:%s(@%d #%d:%s) ", node->id(), node->op()->mnemonic(), 9611cb0ef41Sopenharmony_ci index, input->id(), input->op()->mnemonic()); 9621cb0ef41Sopenharmony_ci TRACE("from %s to %s:%s\n", 9631cb0ef41Sopenharmony_ci MachineReprToString(input_info->representation()), 9641cb0ef41Sopenharmony_ci MachineReprToString(use.representation()), 9651cb0ef41Sopenharmony_ci use.truncation().description()); 9661cb0ef41Sopenharmony_ci if (input_type.IsInvalid()) { 9671cb0ef41Sopenharmony_ci input_type = TypeOf(input); 9681cb0ef41Sopenharmony_ci } 9691cb0ef41Sopenharmony_ci Node* n = changer_->GetRepresentationFor(input, input_rep, input_type, 9701cb0ef41Sopenharmony_ci node, use); 9711cb0ef41Sopenharmony_ci node->ReplaceInput(index, n); 9721cb0ef41Sopenharmony_ci } 9731cb0ef41Sopenharmony_ci } 9741cb0ef41Sopenharmony_ci 9751cb0ef41Sopenharmony_ci template <Phase T> 9761cb0ef41Sopenharmony_ci void ProcessInput(Node* node, int index, UseInfo use); 9771cb0ef41Sopenharmony_ci 9781cb0ef41Sopenharmony_ci // Just assert for Retype and Lower. Propagate specialized below. 9791cb0ef41Sopenharmony_ci template <Phase T> 9801cb0ef41Sopenharmony_ci void ProcessRemainingInputs(Node* node, int index) { 9811cb0ef41Sopenharmony_ci static_assert(retype<T>() || lower<T>(), 9821cb0ef41Sopenharmony_ci "This version of ProcessRemainingInputs has to be called in " 9831cb0ef41Sopenharmony_ci "the Retype or Lower phase."); 9841cb0ef41Sopenharmony_ci DCHECK_GE(index, NodeProperties::PastValueIndex(node)); 9851cb0ef41Sopenharmony_ci DCHECK_GE(index, NodeProperties::PastContextIndex(node)); 9861cb0ef41Sopenharmony_ci } 9871cb0ef41Sopenharmony_ci 9881cb0ef41Sopenharmony_ci // Marks node as a possible revisit since it is a use of input that will be 9891cb0ef41Sopenharmony_ci // visited before input is visited. 9901cb0ef41Sopenharmony_ci void MarkAsPossibleRevisit(Node* node, Node* input) { 9911cb0ef41Sopenharmony_ci auto it = might_need_revisit_.find(input); 9921cb0ef41Sopenharmony_ci if (it == might_need_revisit_.end()) { 9931cb0ef41Sopenharmony_ci it = might_need_revisit_.insert({input, ZoneVector<Node*>(zone())}).first; 9941cb0ef41Sopenharmony_ci } 9951cb0ef41Sopenharmony_ci it->second.push_back(node); 9961cb0ef41Sopenharmony_ci TRACE(" Marking #%d: %s as needing revisit due to #%d: %s\n", node->id(), 9971cb0ef41Sopenharmony_ci node->op()->mnemonic(), input->id(), input->op()->mnemonic()); 9981cb0ef41Sopenharmony_ci } 9991cb0ef41Sopenharmony_ci 10001cb0ef41Sopenharmony_ci // Just assert for Retype. Propagate and Lower specialized below. 10011cb0ef41Sopenharmony_ci template <Phase T> 10021cb0ef41Sopenharmony_ci void VisitInputs(Node* node) { 10031cb0ef41Sopenharmony_ci static_assert( 10041cb0ef41Sopenharmony_ci retype<T>(), 10051cb0ef41Sopenharmony_ci "This version of VisitInputs has to be called in the Retype phase."); 10061cb0ef41Sopenharmony_ci } 10071cb0ef41Sopenharmony_ci 10081cb0ef41Sopenharmony_ci template <Phase T> 10091cb0ef41Sopenharmony_ci void VisitReturn(Node* node) { 10101cb0ef41Sopenharmony_ci int first_effect_index = NodeProperties::FirstEffectIndex(node); 10111cb0ef41Sopenharmony_ci // Visit integer slot count to pop 10121cb0ef41Sopenharmony_ci ProcessInput<T>(node, 0, UseInfo::TruncatingWord32()); 10131cb0ef41Sopenharmony_ci 10141cb0ef41Sopenharmony_ci // Visit value, context and frame state inputs as tagged. 10151cb0ef41Sopenharmony_ci for (int i = 1; i < first_effect_index; i++) { 10161cb0ef41Sopenharmony_ci ProcessInput<T>(node, i, UseInfo::AnyTagged()); 10171cb0ef41Sopenharmony_ci } 10181cb0ef41Sopenharmony_ci // Only enqueue other inputs (effects, control). 10191cb0ef41Sopenharmony_ci for (int i = first_effect_index; i < node->InputCount(); i++) { 10201cb0ef41Sopenharmony_ci EnqueueInput<T>(node, i); 10211cb0ef41Sopenharmony_ci } 10221cb0ef41Sopenharmony_ci } 10231cb0ef41Sopenharmony_ci 10241cb0ef41Sopenharmony_ci // Helper for an unused node. 10251cb0ef41Sopenharmony_ci template <Phase T> 10261cb0ef41Sopenharmony_ci void VisitUnused(Node* node) { 10271cb0ef41Sopenharmony_ci int first_effect_index = NodeProperties::FirstEffectIndex(node); 10281cb0ef41Sopenharmony_ci for (int i = 0; i < first_effect_index; i++) { 10291cb0ef41Sopenharmony_ci ProcessInput<T>(node, i, UseInfo::None()); 10301cb0ef41Sopenharmony_ci } 10311cb0ef41Sopenharmony_ci ProcessRemainingInputs<T>(node, first_effect_index); 10321cb0ef41Sopenharmony_ci 10331cb0ef41Sopenharmony_ci if (lower<T>()) { 10341cb0ef41Sopenharmony_ci TRACE("disconnecting unused #%d:%s\n", node->id(), 10351cb0ef41Sopenharmony_ci node->op()->mnemonic()); 10361cb0ef41Sopenharmony_ci DisconnectFromEffectAndControl(node); 10371cb0ef41Sopenharmony_ci node->NullAllInputs(); // Node is now dead. 10381cb0ef41Sopenharmony_ci DeferReplacement(node, graph()->NewNode(common()->Plug())); 10391cb0ef41Sopenharmony_ci } 10401cb0ef41Sopenharmony_ci } 10411cb0ef41Sopenharmony_ci 10421cb0ef41Sopenharmony_ci // Helper for no-op node. 10431cb0ef41Sopenharmony_ci template <Phase T> 10441cb0ef41Sopenharmony_ci void VisitNoop(Node* node, Truncation truncation) { 10451cb0ef41Sopenharmony_ci if (truncation.IsUnused()) return VisitUnused<T>(node); 10461cb0ef41Sopenharmony_ci MachineRepresentation representation = 10471cb0ef41Sopenharmony_ci GetOutputInfoForPhi(node, TypeOf(node), truncation); 10481cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo(representation, truncation), representation); 10491cb0ef41Sopenharmony_ci if (lower<T>()) DeferReplacement(node, node->InputAt(0)); 10501cb0ef41Sopenharmony_ci } 10511cb0ef41Sopenharmony_ci 10521cb0ef41Sopenharmony_ci // Helper for binops of the R x L -> O variety. 10531cb0ef41Sopenharmony_ci template <Phase T> 10541cb0ef41Sopenharmony_ci void VisitBinop(Node* node, UseInfo left_use, UseInfo right_use, 10551cb0ef41Sopenharmony_ci MachineRepresentation output, 10561cb0ef41Sopenharmony_ci Type restriction_type = Type::Any()) { 10571cb0ef41Sopenharmony_ci DCHECK_EQ(2, node->op()->ValueInputCount()); 10581cb0ef41Sopenharmony_ci ProcessInput<T>(node, 0, left_use); 10591cb0ef41Sopenharmony_ci ProcessInput<T>(node, 1, right_use); 10601cb0ef41Sopenharmony_ci for (int i = 2; i < node->InputCount(); i++) { 10611cb0ef41Sopenharmony_ci EnqueueInput<T>(node, i); 10621cb0ef41Sopenharmony_ci } 10631cb0ef41Sopenharmony_ci SetOutput<T>(node, output, restriction_type); 10641cb0ef41Sopenharmony_ci } 10651cb0ef41Sopenharmony_ci 10661cb0ef41Sopenharmony_ci // Helper for binops of the I x I -> O variety. 10671cb0ef41Sopenharmony_ci template <Phase T> 10681cb0ef41Sopenharmony_ci void VisitBinop(Node* node, UseInfo input_use, MachineRepresentation output, 10691cb0ef41Sopenharmony_ci Type restriction_type = Type::Any()) { 10701cb0ef41Sopenharmony_ci VisitBinop<T>(node, input_use, input_use, output, restriction_type); 10711cb0ef41Sopenharmony_ci } 10721cb0ef41Sopenharmony_ci 10731cb0ef41Sopenharmony_ci template <Phase T> 10741cb0ef41Sopenharmony_ci void VisitSpeculativeInt32Binop(Node* node) { 10751cb0ef41Sopenharmony_ci DCHECK_EQ(2, node->op()->ValueInputCount()); 10761cb0ef41Sopenharmony_ci if (BothInputsAre(node, Type::NumberOrOddball())) { 10771cb0ef41Sopenharmony_ci return VisitBinop<T>(node, UseInfo::TruncatingWord32(), 10781cb0ef41Sopenharmony_ci MachineRepresentation::kWord32); 10791cb0ef41Sopenharmony_ci } 10801cb0ef41Sopenharmony_ci NumberOperationHint hint = NumberOperationHintOf(node->op()); 10811cb0ef41Sopenharmony_ci return VisitBinop<T>(node, 10821cb0ef41Sopenharmony_ci CheckedUseInfoAsWord32FromHint(hint, kIdentifyZeros), 10831cb0ef41Sopenharmony_ci MachineRepresentation::kWord32); 10841cb0ef41Sopenharmony_ci } 10851cb0ef41Sopenharmony_ci 10861cb0ef41Sopenharmony_ci // Helper for unops of the I -> O variety. 10871cb0ef41Sopenharmony_ci template <Phase T> 10881cb0ef41Sopenharmony_ci void VisitUnop(Node* node, UseInfo input_use, MachineRepresentation output, 10891cb0ef41Sopenharmony_ci Type restriction_type = Type::Any()) { 10901cb0ef41Sopenharmony_ci DCHECK_EQ(1, node->op()->ValueInputCount()); 10911cb0ef41Sopenharmony_ci ProcessInput<T>(node, 0, input_use); 10921cb0ef41Sopenharmony_ci ProcessRemainingInputs<T>(node, 1); 10931cb0ef41Sopenharmony_ci SetOutput<T>(node, output, restriction_type); 10941cb0ef41Sopenharmony_ci } 10951cb0ef41Sopenharmony_ci 10961cb0ef41Sopenharmony_ci // Helper for leaf nodes. 10971cb0ef41Sopenharmony_ci template <Phase T> 10981cb0ef41Sopenharmony_ci void VisitLeaf(Node* node, MachineRepresentation output) { 10991cb0ef41Sopenharmony_ci DCHECK_EQ(0, node->InputCount()); 11001cb0ef41Sopenharmony_ci SetOutput<T>(node, output); 11011cb0ef41Sopenharmony_ci } 11021cb0ef41Sopenharmony_ci 11031cb0ef41Sopenharmony_ci // Helpers for specific types of binops. 11041cb0ef41Sopenharmony_ci 11051cb0ef41Sopenharmony_ci template <Phase T> 11061cb0ef41Sopenharmony_ci void VisitFloat64Binop(Node* node) { 11071cb0ef41Sopenharmony_ci VisitBinop<T>(node, UseInfo::TruncatingFloat64(), 11081cb0ef41Sopenharmony_ci MachineRepresentation::kFloat64); 11091cb0ef41Sopenharmony_ci } 11101cb0ef41Sopenharmony_ci 11111cb0ef41Sopenharmony_ci template <Phase T> 11121cb0ef41Sopenharmony_ci void VisitInt64Binop(Node* node) { 11131cb0ef41Sopenharmony_ci VisitBinop<T>(node, UseInfo::Word64(), MachineRepresentation::kWord64); 11141cb0ef41Sopenharmony_ci } 11151cb0ef41Sopenharmony_ci 11161cb0ef41Sopenharmony_ci template <Phase T> 11171cb0ef41Sopenharmony_ci void VisitWord32TruncatingBinop(Node* node) { 11181cb0ef41Sopenharmony_ci VisitBinop<T>(node, UseInfo::TruncatingWord32(), 11191cb0ef41Sopenharmony_ci MachineRepresentation::kWord32); 11201cb0ef41Sopenharmony_ci } 11211cb0ef41Sopenharmony_ci 11221cb0ef41Sopenharmony_ci // Infer representation for phi-like nodes. 11231cb0ef41Sopenharmony_ci // The {node} parameter is only used to decide on the int64 representation. 11241cb0ef41Sopenharmony_ci // Once the type system supports an external pointer type, the {node} 11251cb0ef41Sopenharmony_ci // parameter can be removed. 11261cb0ef41Sopenharmony_ci MachineRepresentation GetOutputInfoForPhi(Node* node, Type type, 11271cb0ef41Sopenharmony_ci Truncation use) { 11281cb0ef41Sopenharmony_ci // Compute the representation. 11291cb0ef41Sopenharmony_ci if (type.Is(Type::None())) { 11301cb0ef41Sopenharmony_ci return MachineRepresentation::kNone; 11311cb0ef41Sopenharmony_ci } else if (type.Is(Type::Signed32()) || type.Is(Type::Unsigned32())) { 11321cb0ef41Sopenharmony_ci return MachineRepresentation::kWord32; 11331cb0ef41Sopenharmony_ci } else if (type.Is(Type::NumberOrOddball()) && use.IsUsedAsWord32()) { 11341cb0ef41Sopenharmony_ci return MachineRepresentation::kWord32; 11351cb0ef41Sopenharmony_ci } else if (type.Is(Type::Boolean())) { 11361cb0ef41Sopenharmony_ci return MachineRepresentation::kBit; 11371cb0ef41Sopenharmony_ci } else if (type.Is(Type::NumberOrOddball()) && 11381cb0ef41Sopenharmony_ci use.TruncatesOddballAndBigIntToNumber()) { 11391cb0ef41Sopenharmony_ci return MachineRepresentation::kFloat64; 11401cb0ef41Sopenharmony_ci } else if (type.Is(Type::Union(Type::SignedSmall(), Type::NaN(), zone()))) { 11411cb0ef41Sopenharmony_ci // TODO(turbofan): For Phis that return either NaN or some Smi, it's 11421cb0ef41Sopenharmony_ci // beneficial to not go all the way to double, unless the uses are 11431cb0ef41Sopenharmony_ci // double uses. For tagging that just means some potentially expensive 11441cb0ef41Sopenharmony_ci // allocation code; we might want to do the same for -0 as well? 11451cb0ef41Sopenharmony_ci return MachineRepresentation::kTagged; 11461cb0ef41Sopenharmony_ci } else if (type.Is(Type::Number())) { 11471cb0ef41Sopenharmony_ci return MachineRepresentation::kFloat64; 11481cb0ef41Sopenharmony_ci } else if (type.Is(Type::BigInt()) && use.IsUsedAsWord64()) { 11491cb0ef41Sopenharmony_ci return MachineRepresentation::kWord64; 11501cb0ef41Sopenharmony_ci } else if (type.Is(Type::ExternalPointer()) || 11511cb0ef41Sopenharmony_ci type.Is(Type::SandboxedPointer())) { 11521cb0ef41Sopenharmony_ci return MachineType::PointerRepresentation(); 11531cb0ef41Sopenharmony_ci } 11541cb0ef41Sopenharmony_ci return MachineRepresentation::kTagged; 11551cb0ef41Sopenharmony_ci } 11561cb0ef41Sopenharmony_ci 11571cb0ef41Sopenharmony_ci // Helper for handling selects. 11581cb0ef41Sopenharmony_ci template <Phase T> 11591cb0ef41Sopenharmony_ci void VisitSelect(Node* node, Truncation truncation, 11601cb0ef41Sopenharmony_ci SimplifiedLowering* lowering) { 11611cb0ef41Sopenharmony_ci DCHECK(TypeOf(node->InputAt(0)).Is(Type::Boolean())); 11621cb0ef41Sopenharmony_ci ProcessInput<T>(node, 0, UseInfo::Bool()); 11631cb0ef41Sopenharmony_ci 11641cb0ef41Sopenharmony_ci MachineRepresentation output = 11651cb0ef41Sopenharmony_ci GetOutputInfoForPhi(node, TypeOf(node), truncation); 11661cb0ef41Sopenharmony_ci SetOutput<T>(node, output); 11671cb0ef41Sopenharmony_ci 11681cb0ef41Sopenharmony_ci if (lower<T>()) { 11691cb0ef41Sopenharmony_ci // Update the select operator. 11701cb0ef41Sopenharmony_ci SelectParameters p = SelectParametersOf(node->op()); 11711cb0ef41Sopenharmony_ci if (output != p.representation()) { 11721cb0ef41Sopenharmony_ci ChangeOp(node, lowering->common()->Select(output, p.hint())); 11731cb0ef41Sopenharmony_ci } 11741cb0ef41Sopenharmony_ci } 11751cb0ef41Sopenharmony_ci // Convert inputs to the output representation of this phi, pass the 11761cb0ef41Sopenharmony_ci // truncation truncation along. 11771cb0ef41Sopenharmony_ci UseInfo input_use(output, truncation); 11781cb0ef41Sopenharmony_ci ProcessInput<T>(node, 1, input_use); 11791cb0ef41Sopenharmony_ci ProcessInput<T>(node, 2, input_use); 11801cb0ef41Sopenharmony_ci } 11811cb0ef41Sopenharmony_ci 11821cb0ef41Sopenharmony_ci // Helper for handling phis. 11831cb0ef41Sopenharmony_ci template <Phase T> 11841cb0ef41Sopenharmony_ci void VisitPhi(Node* node, Truncation truncation, 11851cb0ef41Sopenharmony_ci SimplifiedLowering* lowering) { 11861cb0ef41Sopenharmony_ci MachineRepresentation output = 11871cb0ef41Sopenharmony_ci GetOutputInfoForPhi(node, TypeOf(node), truncation); 11881cb0ef41Sopenharmony_ci // Only set the output representation if not running with type 11891cb0ef41Sopenharmony_ci // feedback. (Feedback typing will set the representation.) 11901cb0ef41Sopenharmony_ci SetOutput<T>(node, output); 11911cb0ef41Sopenharmony_ci 11921cb0ef41Sopenharmony_ci int values = node->op()->ValueInputCount(); 11931cb0ef41Sopenharmony_ci if (lower<T>()) { 11941cb0ef41Sopenharmony_ci // Update the phi operator. 11951cb0ef41Sopenharmony_ci if (output != PhiRepresentationOf(node->op())) { 11961cb0ef41Sopenharmony_ci ChangeOp(node, lowering->common()->Phi(output, values)); 11971cb0ef41Sopenharmony_ci } 11981cb0ef41Sopenharmony_ci } 11991cb0ef41Sopenharmony_ci 12001cb0ef41Sopenharmony_ci // Convert inputs to the output representation of this phi, pass the 12011cb0ef41Sopenharmony_ci // truncation along. 12021cb0ef41Sopenharmony_ci UseInfo input_use(output, truncation); 12031cb0ef41Sopenharmony_ci for (int i = 0; i < node->InputCount(); i++) { 12041cb0ef41Sopenharmony_ci ProcessInput<T>(node, i, i < values ? input_use : UseInfo::None()); 12051cb0ef41Sopenharmony_ci } 12061cb0ef41Sopenharmony_ci } 12071cb0ef41Sopenharmony_ci 12081cb0ef41Sopenharmony_ci template <Phase T> 12091cb0ef41Sopenharmony_ci void VisitObjectIs(Node* node, Type type, SimplifiedLowering* lowering) { 12101cb0ef41Sopenharmony_ci Type const input_type = TypeOf(node->InputAt(0)); 12111cb0ef41Sopenharmony_ci if (input_type.Is(type)) { 12121cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::None(), MachineRepresentation::kBit); 12131cb0ef41Sopenharmony_ci if (lower<T>()) { 12141cb0ef41Sopenharmony_ci DeferReplacement(node, lowering->jsgraph()->Int32Constant(1)); 12151cb0ef41Sopenharmony_ci } 12161cb0ef41Sopenharmony_ci } else { 12171cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::AnyTagged(), MachineRepresentation::kBit); 12181cb0ef41Sopenharmony_ci if (lower<T>() && !input_type.Maybe(type)) { 12191cb0ef41Sopenharmony_ci DeferReplacement(node, lowering->jsgraph()->Int32Constant(0)); 12201cb0ef41Sopenharmony_ci } 12211cb0ef41Sopenharmony_ci } 12221cb0ef41Sopenharmony_ci } 12231cb0ef41Sopenharmony_ci 12241cb0ef41Sopenharmony_ci template <Phase T> 12251cb0ef41Sopenharmony_ci void VisitCheck(Node* node, Type type, SimplifiedLowering* lowering) { 12261cb0ef41Sopenharmony_ci if (InputIs(node, type)) { 12271cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::AnyTagged(), 12281cb0ef41Sopenharmony_ci MachineRepresentation::kTaggedPointer); 12291cb0ef41Sopenharmony_ci if (lower<T>()) DeferReplacement(node, node->InputAt(0)); 12301cb0ef41Sopenharmony_ci } else { 12311cb0ef41Sopenharmony_ci VisitUnop<T>(node, 12321cb0ef41Sopenharmony_ci UseInfo::CheckedHeapObjectAsTaggedPointer(FeedbackSource()), 12331cb0ef41Sopenharmony_ci MachineRepresentation::kTaggedPointer); 12341cb0ef41Sopenharmony_ci } 12351cb0ef41Sopenharmony_ci } 12361cb0ef41Sopenharmony_ci 12371cb0ef41Sopenharmony_ci template <Phase T> 12381cb0ef41Sopenharmony_ci void VisitCall(Node* node, SimplifiedLowering* lowering) { 12391cb0ef41Sopenharmony_ci auto call_descriptor = CallDescriptorOf(node->op()); 12401cb0ef41Sopenharmony_ci int params = static_cast<int>(call_descriptor->ParameterCount()); 12411cb0ef41Sopenharmony_ci int value_input_count = node->op()->ValueInputCount(); 12421cb0ef41Sopenharmony_ci 12431cb0ef41Sopenharmony_ci DCHECK_GT(value_input_count, 0); 12441cb0ef41Sopenharmony_ci DCHECK_GE(value_input_count, params); 12451cb0ef41Sopenharmony_ci 12461cb0ef41Sopenharmony_ci // The target of the call. 12471cb0ef41Sopenharmony_ci ProcessInput<T>(node, 0, UseInfo::Any()); 12481cb0ef41Sopenharmony_ci 12491cb0ef41Sopenharmony_ci // For the parameters (indexes [1, ..., params]), propagate representation 12501cb0ef41Sopenharmony_ci // information from call descriptor. 12511cb0ef41Sopenharmony_ci for (int i = 1; i <= params; i++) { 12521cb0ef41Sopenharmony_ci ProcessInput<T>(node, i, 12531cb0ef41Sopenharmony_ci TruncatingUseInfoFromRepresentation( 12541cb0ef41Sopenharmony_ci call_descriptor->GetInputType(i).representation())); 12551cb0ef41Sopenharmony_ci } 12561cb0ef41Sopenharmony_ci 12571cb0ef41Sopenharmony_ci // Rest of the value inputs. 12581cb0ef41Sopenharmony_ci for (int i = params + 1; i < value_input_count; i++) { 12591cb0ef41Sopenharmony_ci ProcessInput<T>(node, i, UseInfo::AnyTagged()); 12601cb0ef41Sopenharmony_ci } 12611cb0ef41Sopenharmony_ci 12621cb0ef41Sopenharmony_ci // Effect and Control. 12631cb0ef41Sopenharmony_ci ProcessRemainingInputs<T>(node, value_input_count); 12641cb0ef41Sopenharmony_ci 12651cb0ef41Sopenharmony_ci if (call_descriptor->ReturnCount() > 0) { 12661cb0ef41Sopenharmony_ci SetOutput<T>(node, call_descriptor->GetReturnType(0).representation()); 12671cb0ef41Sopenharmony_ci } else { 12681cb0ef41Sopenharmony_ci SetOutput<T>(node, MachineRepresentation::kTagged); 12691cb0ef41Sopenharmony_ci } 12701cb0ef41Sopenharmony_ci } 12711cb0ef41Sopenharmony_ci 12721cb0ef41Sopenharmony_ci void MaskShiftOperand(Node* node, Type rhs_type) { 12731cb0ef41Sopenharmony_ci if (!rhs_type.Is(type_cache_->kZeroToThirtyOne)) { 12741cb0ef41Sopenharmony_ci Node* const rhs = NodeProperties::GetValueInput(node, 1); 12751cb0ef41Sopenharmony_ci node->ReplaceInput(1, 12761cb0ef41Sopenharmony_ci graph()->NewNode(jsgraph_->machine()->Word32And(), rhs, 12771cb0ef41Sopenharmony_ci jsgraph_->Int32Constant(0x1F))); 12781cb0ef41Sopenharmony_ci } 12791cb0ef41Sopenharmony_ci } 12801cb0ef41Sopenharmony_ci 12811cb0ef41Sopenharmony_ci static MachineSemantic DeoptValueSemanticOf(Type type) { 12821cb0ef41Sopenharmony_ci // We only need signedness to do deopt correctly. 12831cb0ef41Sopenharmony_ci if (type.Is(Type::Signed32())) { 12841cb0ef41Sopenharmony_ci return MachineSemantic::kInt32; 12851cb0ef41Sopenharmony_ci } else if (type.Is(Type::Unsigned32())) { 12861cb0ef41Sopenharmony_ci return MachineSemantic::kUint32; 12871cb0ef41Sopenharmony_ci } else { 12881cb0ef41Sopenharmony_ci return MachineSemantic::kAny; 12891cb0ef41Sopenharmony_ci } 12901cb0ef41Sopenharmony_ci } 12911cb0ef41Sopenharmony_ci 12921cb0ef41Sopenharmony_ci static MachineType DeoptMachineTypeOf(MachineRepresentation rep, Type type) { 12931cb0ef41Sopenharmony_ci if (type.IsNone()) { 12941cb0ef41Sopenharmony_ci return MachineType::None(); 12951cb0ef41Sopenharmony_ci } 12961cb0ef41Sopenharmony_ci // Do not distinguish between various Tagged variations. 12971cb0ef41Sopenharmony_ci if (IsAnyTagged(rep)) { 12981cb0ef41Sopenharmony_ci return MachineType::AnyTagged(); 12991cb0ef41Sopenharmony_ci } 13001cb0ef41Sopenharmony_ci if (rep == MachineRepresentation::kWord64) { 13011cb0ef41Sopenharmony_ci if (type.Is(Type::BigInt())) { 13021cb0ef41Sopenharmony_ci return MachineType::AnyTagged(); 13031cb0ef41Sopenharmony_ci } 13041cb0ef41Sopenharmony_ci 13051cb0ef41Sopenharmony_ci DCHECK(type.Is(TypeCache::Get()->kSafeInteger)); 13061cb0ef41Sopenharmony_ci return MachineType(rep, MachineSemantic::kInt64); 13071cb0ef41Sopenharmony_ci } 13081cb0ef41Sopenharmony_ci MachineType machine_type(rep, DeoptValueSemanticOf(type)); 13091cb0ef41Sopenharmony_ci DCHECK(machine_type.representation() != MachineRepresentation::kWord32 || 13101cb0ef41Sopenharmony_ci machine_type.semantic() == MachineSemantic::kInt32 || 13111cb0ef41Sopenharmony_ci machine_type.semantic() == MachineSemantic::kUint32); 13121cb0ef41Sopenharmony_ci DCHECK(machine_type.representation() != MachineRepresentation::kBit || 13131cb0ef41Sopenharmony_ci type.Is(Type::Boolean())); 13141cb0ef41Sopenharmony_ci return machine_type; 13151cb0ef41Sopenharmony_ci } 13161cb0ef41Sopenharmony_ci 13171cb0ef41Sopenharmony_ci template <Phase T> 13181cb0ef41Sopenharmony_ci void VisitStateValues(Node* node) { 13191cb0ef41Sopenharmony_ci if (propagate<T>()) { 13201cb0ef41Sopenharmony_ci for (int i = 0; i < node->InputCount(); i++) { 13211cb0ef41Sopenharmony_ci // When lowering 64 bit BigInts to Word64 representation, we have to 13221cb0ef41Sopenharmony_ci // make sure they are rematerialized before deoptimization. By 13231cb0ef41Sopenharmony_ci // propagating a AnyTagged use, the RepresentationChanger is going to 13241cb0ef41Sopenharmony_ci // insert the necessary conversions. 13251cb0ef41Sopenharmony_ci // TODO(nicohartmann): Remove, once the deoptimizer can rematerialize 13261cb0ef41Sopenharmony_ci // truncated BigInts. 13271cb0ef41Sopenharmony_ci if (TypeOf(node->InputAt(i)).Is(Type::BigInt())) { 13281cb0ef41Sopenharmony_ci EnqueueInput<T>(node, i, UseInfo::AnyTagged()); 13291cb0ef41Sopenharmony_ci } else { 13301cb0ef41Sopenharmony_ci EnqueueInput<T>(node, i, UseInfo::Any()); 13311cb0ef41Sopenharmony_ci } 13321cb0ef41Sopenharmony_ci } 13331cb0ef41Sopenharmony_ci } else if (lower<T>()) { 13341cb0ef41Sopenharmony_ci Zone* zone = jsgraph_->zone(); 13351cb0ef41Sopenharmony_ci ZoneVector<MachineType>* types = 13361cb0ef41Sopenharmony_ci zone->New<ZoneVector<MachineType>>(node->InputCount(), zone); 13371cb0ef41Sopenharmony_ci for (int i = 0; i < node->InputCount(); i++) { 13381cb0ef41Sopenharmony_ci Node* input = node->InputAt(i); 13391cb0ef41Sopenharmony_ci // TODO(nicohartmann): Remove, once the deoptimizer can rematerialize 13401cb0ef41Sopenharmony_ci // truncated BigInts. 13411cb0ef41Sopenharmony_ci if (TypeOf(input).Is(Type::BigInt())) { 13421cb0ef41Sopenharmony_ci ConvertInput(node, i, UseInfo::AnyTagged()); 13431cb0ef41Sopenharmony_ci } 13441cb0ef41Sopenharmony_ci 13451cb0ef41Sopenharmony_ci (*types)[i] = 13461cb0ef41Sopenharmony_ci DeoptMachineTypeOf(GetInfo(input)->representation(), TypeOf(input)); 13471cb0ef41Sopenharmony_ci } 13481cb0ef41Sopenharmony_ci SparseInputMask mask = SparseInputMaskOf(node->op()); 13491cb0ef41Sopenharmony_ci ChangeOp(node, common()->TypedStateValues(types, mask)); 13501cb0ef41Sopenharmony_ci } 13511cb0ef41Sopenharmony_ci SetOutput<T>(node, MachineRepresentation::kTagged); 13521cb0ef41Sopenharmony_ci } 13531cb0ef41Sopenharmony_ci 13541cb0ef41Sopenharmony_ci template <Phase T> 13551cb0ef41Sopenharmony_ci void VisitFrameState(FrameState node) { 13561cb0ef41Sopenharmony_ci DCHECK_EQ(5, node->op()->ValueInputCount()); 13571cb0ef41Sopenharmony_ci DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op())); 13581cb0ef41Sopenharmony_ci DCHECK_EQ(FrameState::kFrameStateInputCount, node->InputCount()); 13591cb0ef41Sopenharmony_ci 13601cb0ef41Sopenharmony_ci ProcessInput<T>(node, FrameState::kFrameStateParametersInput, 13611cb0ef41Sopenharmony_ci UseInfo::AnyTagged()); 13621cb0ef41Sopenharmony_ci ProcessInput<T>(node, FrameState::kFrameStateLocalsInput, 13631cb0ef41Sopenharmony_ci UseInfo::AnyTagged()); 13641cb0ef41Sopenharmony_ci 13651cb0ef41Sopenharmony_ci // Accumulator is a special flower - we need to remember its type in 13661cb0ef41Sopenharmony_ci // a singleton typed-state-values node (as if it was a singleton 13671cb0ef41Sopenharmony_ci // state-values node). 13681cb0ef41Sopenharmony_ci Node* accumulator = node.stack(); 13691cb0ef41Sopenharmony_ci if (propagate<T>()) { 13701cb0ef41Sopenharmony_ci // TODO(nicohartmann): Remove, once the deoptimizer can rematerialize 13711cb0ef41Sopenharmony_ci // truncated BigInts. 13721cb0ef41Sopenharmony_ci if (TypeOf(accumulator).Is(Type::BigInt())) { 13731cb0ef41Sopenharmony_ci EnqueueInput<T>(node, FrameState::kFrameStateStackInput, 13741cb0ef41Sopenharmony_ci UseInfo::AnyTagged()); 13751cb0ef41Sopenharmony_ci } else { 13761cb0ef41Sopenharmony_ci EnqueueInput<T>(node, FrameState::kFrameStateStackInput, 13771cb0ef41Sopenharmony_ci UseInfo::Any()); 13781cb0ef41Sopenharmony_ci } 13791cb0ef41Sopenharmony_ci } else if (lower<T>()) { 13801cb0ef41Sopenharmony_ci // TODO(nicohartmann): Remove, once the deoptimizer can rematerialize 13811cb0ef41Sopenharmony_ci // truncated BigInts. 13821cb0ef41Sopenharmony_ci if (TypeOf(accumulator).Is(Type::BigInt())) { 13831cb0ef41Sopenharmony_ci ConvertInput(node, FrameState::kFrameStateStackInput, 13841cb0ef41Sopenharmony_ci UseInfo::AnyTagged()); 13851cb0ef41Sopenharmony_ci } 13861cb0ef41Sopenharmony_ci Zone* zone = jsgraph_->zone(); 13871cb0ef41Sopenharmony_ci if (accumulator == jsgraph_->OptimizedOutConstant()) { 13881cb0ef41Sopenharmony_ci node->ReplaceInput(FrameState::kFrameStateStackInput, 13891cb0ef41Sopenharmony_ci jsgraph_->SingleDeadTypedStateValues()); 13901cb0ef41Sopenharmony_ci } else { 13911cb0ef41Sopenharmony_ci ZoneVector<MachineType>* types = 13921cb0ef41Sopenharmony_ci zone->New<ZoneVector<MachineType>>(1, zone); 13931cb0ef41Sopenharmony_ci (*types)[0] = DeoptMachineTypeOf(GetInfo(accumulator)->representation(), 13941cb0ef41Sopenharmony_ci TypeOf(accumulator)); 13951cb0ef41Sopenharmony_ci 13961cb0ef41Sopenharmony_ci node->ReplaceInput( 13971cb0ef41Sopenharmony_ci FrameState::kFrameStateStackInput, 13981cb0ef41Sopenharmony_ci jsgraph_->graph()->NewNode( 13991cb0ef41Sopenharmony_ci common()->TypedStateValues(types, SparseInputMask::Dense()), 14001cb0ef41Sopenharmony_ci node.stack())); 14011cb0ef41Sopenharmony_ci } 14021cb0ef41Sopenharmony_ci } 14031cb0ef41Sopenharmony_ci 14041cb0ef41Sopenharmony_ci ProcessInput<T>(node, FrameState::kFrameStateContextInput, 14051cb0ef41Sopenharmony_ci UseInfo::AnyTagged()); 14061cb0ef41Sopenharmony_ci ProcessInput<T>(node, FrameState::kFrameStateFunctionInput, 14071cb0ef41Sopenharmony_ci UseInfo::AnyTagged()); 14081cb0ef41Sopenharmony_ci ProcessInput<T>(node, FrameState::kFrameStateOuterStateInput, 14091cb0ef41Sopenharmony_ci UseInfo::AnyTagged()); 14101cb0ef41Sopenharmony_ci return SetOutput<T>(node, MachineRepresentation::kTagged); 14111cb0ef41Sopenharmony_ci } 14121cb0ef41Sopenharmony_ci 14131cb0ef41Sopenharmony_ci template <Phase T> 14141cb0ef41Sopenharmony_ci void VisitObjectState(Node* node) { 14151cb0ef41Sopenharmony_ci if (propagate<T>()) { 14161cb0ef41Sopenharmony_ci for (int i = 0; i < node->InputCount(); i++) { 14171cb0ef41Sopenharmony_ci // TODO(nicohartmann): Remove, once the deoptimizer can rematerialize 14181cb0ef41Sopenharmony_ci // truncated BigInts. 14191cb0ef41Sopenharmony_ci if (TypeOf(node->InputAt(i)).Is(Type::BigInt())) { 14201cb0ef41Sopenharmony_ci EnqueueInput<T>(node, i, UseInfo::AnyTagged()); 14211cb0ef41Sopenharmony_ci } else { 14221cb0ef41Sopenharmony_ci EnqueueInput<T>(node, i, UseInfo::Any()); 14231cb0ef41Sopenharmony_ci } 14241cb0ef41Sopenharmony_ci } 14251cb0ef41Sopenharmony_ci } else if (lower<T>()) { 14261cb0ef41Sopenharmony_ci Zone* zone = jsgraph_->zone(); 14271cb0ef41Sopenharmony_ci ZoneVector<MachineType>* types = 14281cb0ef41Sopenharmony_ci zone->New<ZoneVector<MachineType>>(node->InputCount(), zone); 14291cb0ef41Sopenharmony_ci for (int i = 0; i < node->InputCount(); i++) { 14301cb0ef41Sopenharmony_ci Node* input = node->InputAt(i); 14311cb0ef41Sopenharmony_ci (*types)[i] = 14321cb0ef41Sopenharmony_ci DeoptMachineTypeOf(GetInfo(input)->representation(), TypeOf(input)); 14331cb0ef41Sopenharmony_ci // TODO(nicohartmann): Remove, once the deoptimizer can rematerialize 14341cb0ef41Sopenharmony_ci // truncated BigInts. 14351cb0ef41Sopenharmony_ci if (TypeOf(node->InputAt(i)).Is(Type::BigInt())) { 14361cb0ef41Sopenharmony_ci ConvertInput(node, i, UseInfo::AnyTagged()); 14371cb0ef41Sopenharmony_ci } 14381cb0ef41Sopenharmony_ci } 14391cb0ef41Sopenharmony_ci ChangeOp(node, common()->TypedObjectState(ObjectIdOf(node->op()), types)); 14401cb0ef41Sopenharmony_ci } 14411cb0ef41Sopenharmony_ci SetOutput<T>(node, MachineRepresentation::kTagged); 14421cb0ef41Sopenharmony_ci } 14431cb0ef41Sopenharmony_ci 14441cb0ef41Sopenharmony_ci const Operator* Int32Op(Node* node) { 14451cb0ef41Sopenharmony_ci return changer_->Int32OperatorFor(node->opcode()); 14461cb0ef41Sopenharmony_ci } 14471cb0ef41Sopenharmony_ci 14481cb0ef41Sopenharmony_ci const Operator* Int32OverflowOp(Node* node) { 14491cb0ef41Sopenharmony_ci return changer_->Int32OverflowOperatorFor(node->opcode()); 14501cb0ef41Sopenharmony_ci } 14511cb0ef41Sopenharmony_ci 14521cb0ef41Sopenharmony_ci const Operator* Int64Op(Node* node) { 14531cb0ef41Sopenharmony_ci return changer_->Int64OperatorFor(node->opcode()); 14541cb0ef41Sopenharmony_ci } 14551cb0ef41Sopenharmony_ci 14561cb0ef41Sopenharmony_ci const Operator* Uint32Op(Node* node) { 14571cb0ef41Sopenharmony_ci return changer_->Uint32OperatorFor(node->opcode()); 14581cb0ef41Sopenharmony_ci } 14591cb0ef41Sopenharmony_ci 14601cb0ef41Sopenharmony_ci const Operator* Uint32OverflowOp(Node* node) { 14611cb0ef41Sopenharmony_ci return changer_->Uint32OverflowOperatorFor(node->opcode()); 14621cb0ef41Sopenharmony_ci } 14631cb0ef41Sopenharmony_ci 14641cb0ef41Sopenharmony_ci const Operator* Float64Op(Node* node) { 14651cb0ef41Sopenharmony_ci return changer_->Float64OperatorFor(node->opcode()); 14661cb0ef41Sopenharmony_ci } 14671cb0ef41Sopenharmony_ci 14681cb0ef41Sopenharmony_ci WriteBarrierKind WriteBarrierKindFor( 14691cb0ef41Sopenharmony_ci BaseTaggedness base_taggedness, 14701cb0ef41Sopenharmony_ci MachineRepresentation field_representation, Type field_type, 14711cb0ef41Sopenharmony_ci MachineRepresentation value_representation, Node* value) { 14721cb0ef41Sopenharmony_ci if (base_taggedness == kTaggedBase && 14731cb0ef41Sopenharmony_ci CanBeTaggedPointer(field_representation)) { 14741cb0ef41Sopenharmony_ci Type value_type = NodeProperties::GetType(value); 14751cb0ef41Sopenharmony_ci if (value_representation == MachineRepresentation::kTaggedSigned) { 14761cb0ef41Sopenharmony_ci // Write barriers are only for stores of heap objects. 14771cb0ef41Sopenharmony_ci return kNoWriteBarrier; 14781cb0ef41Sopenharmony_ci } 14791cb0ef41Sopenharmony_ci if (field_type.Is(Type::BooleanOrNullOrUndefined()) || 14801cb0ef41Sopenharmony_ci value_type.Is(Type::BooleanOrNullOrUndefined())) { 14811cb0ef41Sopenharmony_ci // Write barriers are not necessary when storing true, false, null or 14821cb0ef41Sopenharmony_ci // undefined, because these special oddballs are always in the root set. 14831cb0ef41Sopenharmony_ci return kNoWriteBarrier; 14841cb0ef41Sopenharmony_ci } 14851cb0ef41Sopenharmony_ci if (value_type.IsHeapConstant()) { 14861cb0ef41Sopenharmony_ci RootIndex root_index; 14871cb0ef41Sopenharmony_ci const RootsTable& roots_table = jsgraph_->isolate()->roots_table(); 14881cb0ef41Sopenharmony_ci if (roots_table.IsRootHandle(value_type.AsHeapConstant()->Value(), 14891cb0ef41Sopenharmony_ci &root_index)) { 14901cb0ef41Sopenharmony_ci if (RootsTable::IsImmortalImmovable(root_index)) { 14911cb0ef41Sopenharmony_ci // Write barriers are unnecessary for immortal immovable roots. 14921cb0ef41Sopenharmony_ci return kNoWriteBarrier; 14931cb0ef41Sopenharmony_ci } 14941cb0ef41Sopenharmony_ci } 14951cb0ef41Sopenharmony_ci } 14961cb0ef41Sopenharmony_ci if (field_representation == MachineRepresentation::kTaggedPointer || 14971cb0ef41Sopenharmony_ci value_representation == MachineRepresentation::kTaggedPointer) { 14981cb0ef41Sopenharmony_ci // Write barriers for heap objects are cheaper. 14991cb0ef41Sopenharmony_ci return kPointerWriteBarrier; 15001cb0ef41Sopenharmony_ci } 15011cb0ef41Sopenharmony_ci NumberMatcher m(value); 15021cb0ef41Sopenharmony_ci if (m.HasResolvedValue()) { 15031cb0ef41Sopenharmony_ci if (IsSmiDouble(m.ResolvedValue())) { 15041cb0ef41Sopenharmony_ci // Storing a smi doesn't need a write barrier. 15051cb0ef41Sopenharmony_ci return kNoWriteBarrier; 15061cb0ef41Sopenharmony_ci } 15071cb0ef41Sopenharmony_ci // The NumberConstant will be represented as HeapNumber. 15081cb0ef41Sopenharmony_ci return kPointerWriteBarrier; 15091cb0ef41Sopenharmony_ci } 15101cb0ef41Sopenharmony_ci return kFullWriteBarrier; 15111cb0ef41Sopenharmony_ci } 15121cb0ef41Sopenharmony_ci return kNoWriteBarrier; 15131cb0ef41Sopenharmony_ci } 15141cb0ef41Sopenharmony_ci 15151cb0ef41Sopenharmony_ci WriteBarrierKind WriteBarrierKindFor( 15161cb0ef41Sopenharmony_ci BaseTaggedness base_taggedness, 15171cb0ef41Sopenharmony_ci MachineRepresentation field_representation, int field_offset, 15181cb0ef41Sopenharmony_ci Type field_type, MachineRepresentation value_representation, 15191cb0ef41Sopenharmony_ci Node* value) { 15201cb0ef41Sopenharmony_ci WriteBarrierKind write_barrier_kind = 15211cb0ef41Sopenharmony_ci WriteBarrierKindFor(base_taggedness, field_representation, field_type, 15221cb0ef41Sopenharmony_ci value_representation, value); 15231cb0ef41Sopenharmony_ci if (write_barrier_kind != kNoWriteBarrier) { 15241cb0ef41Sopenharmony_ci if (base_taggedness == kTaggedBase && 15251cb0ef41Sopenharmony_ci field_offset == HeapObject::kMapOffset) { 15261cb0ef41Sopenharmony_ci write_barrier_kind = kMapWriteBarrier; 15271cb0ef41Sopenharmony_ci } 15281cb0ef41Sopenharmony_ci } 15291cb0ef41Sopenharmony_ci return write_barrier_kind; 15301cb0ef41Sopenharmony_ci } 15311cb0ef41Sopenharmony_ci 15321cb0ef41Sopenharmony_ci Graph* graph() const { return jsgraph_->graph(); } 15331cb0ef41Sopenharmony_ci CommonOperatorBuilder* common() const { return jsgraph_->common(); } 15341cb0ef41Sopenharmony_ci SimplifiedOperatorBuilder* simplified() const { 15351cb0ef41Sopenharmony_ci return jsgraph_->simplified(); 15361cb0ef41Sopenharmony_ci } 15371cb0ef41Sopenharmony_ci 15381cb0ef41Sopenharmony_ci template <Phase T> 15391cb0ef41Sopenharmony_ci void VisitForCheckedInt32Mul(Node* node, Truncation truncation, 15401cb0ef41Sopenharmony_ci Type input0_type, Type input1_type, 15411cb0ef41Sopenharmony_ci UseInfo input_use) { 15421cb0ef41Sopenharmony_ci DCHECK_EQ(node->opcode(), IrOpcode::kSpeculativeNumberMultiply); 15431cb0ef41Sopenharmony_ci // A -0 input is impossible or will cause a deopt. 15441cb0ef41Sopenharmony_ci DCHECK(BothInputsAre(node, Type::Signed32()) || 15451cb0ef41Sopenharmony_ci !input_use.truncation().IdentifiesZeroAndMinusZero()); 15461cb0ef41Sopenharmony_ci 15471cb0ef41Sopenharmony_ci CheckForMinusZeroMode mz_mode; 15481cb0ef41Sopenharmony_ci Type restriction; 15491cb0ef41Sopenharmony_ci if (IsSomePositiveOrderedNumber(input0_type) || 15501cb0ef41Sopenharmony_ci IsSomePositiveOrderedNumber(input1_type)) { 15511cb0ef41Sopenharmony_ci mz_mode = CheckForMinusZeroMode::kDontCheckForMinusZero; 15521cb0ef41Sopenharmony_ci restriction = Type::Signed32(); 15531cb0ef41Sopenharmony_ci } else if (truncation.IdentifiesZeroAndMinusZero()) { 15541cb0ef41Sopenharmony_ci mz_mode = CheckForMinusZeroMode::kDontCheckForMinusZero; 15551cb0ef41Sopenharmony_ci restriction = Type::Signed32OrMinusZero(); 15561cb0ef41Sopenharmony_ci } else { 15571cb0ef41Sopenharmony_ci mz_mode = CheckForMinusZeroMode::kCheckForMinusZero; 15581cb0ef41Sopenharmony_ci restriction = Type::Signed32(); 15591cb0ef41Sopenharmony_ci } 15601cb0ef41Sopenharmony_ci 15611cb0ef41Sopenharmony_ci VisitBinop<T>(node, input_use, MachineRepresentation::kWord32, restriction); 15621cb0ef41Sopenharmony_ci if (lower<T>()) ChangeOp(node, simplified()->CheckedInt32Mul(mz_mode)); 15631cb0ef41Sopenharmony_ci } 15641cb0ef41Sopenharmony_ci 15651cb0ef41Sopenharmony_ci void ChangeToInt32OverflowOp(Node* node) { 15661cb0ef41Sopenharmony_ci ChangeOp(node, Int32OverflowOp(node)); 15671cb0ef41Sopenharmony_ci } 15681cb0ef41Sopenharmony_ci 15691cb0ef41Sopenharmony_ci void ChangeToUint32OverflowOp(Node* node) { 15701cb0ef41Sopenharmony_ci ChangeOp(node, Uint32OverflowOp(node)); 15711cb0ef41Sopenharmony_ci } 15721cb0ef41Sopenharmony_ci 15731cb0ef41Sopenharmony_ci template <Phase T> 15741cb0ef41Sopenharmony_ci void VisitSpeculativeIntegerAdditiveOp(Node* node, Truncation truncation, 15751cb0ef41Sopenharmony_ci SimplifiedLowering* lowering) { 15761cb0ef41Sopenharmony_ci Type left_upper = GetUpperBound(node->InputAt(0)); 15771cb0ef41Sopenharmony_ci Type right_upper = GetUpperBound(node->InputAt(1)); 15781cb0ef41Sopenharmony_ci 15791cb0ef41Sopenharmony_ci if (left_upper.Is(type_cache_->kAdditiveSafeIntegerOrMinusZero) && 15801cb0ef41Sopenharmony_ci right_upper.Is(type_cache_->kAdditiveSafeIntegerOrMinusZero)) { 15811cb0ef41Sopenharmony_ci // Only eliminate the node if its typing rule can be satisfied, namely 15821cb0ef41Sopenharmony_ci // that a safe integer is produced. 15831cb0ef41Sopenharmony_ci if (truncation.IsUnused()) return VisitUnused<T>(node); 15841cb0ef41Sopenharmony_ci 15851cb0ef41Sopenharmony_ci // If we know how to interpret the result or if the users only care 15861cb0ef41Sopenharmony_ci // about the low 32-bits, we can truncate to Word32 do a wrapping 15871cb0ef41Sopenharmony_ci // addition. 15881cb0ef41Sopenharmony_ci if (GetUpperBound(node).Is(Type::Signed32()) || 15891cb0ef41Sopenharmony_ci GetUpperBound(node).Is(Type::Unsigned32()) || 15901cb0ef41Sopenharmony_ci truncation.IsUsedAsWord32()) { 15911cb0ef41Sopenharmony_ci // => Int32Add/Sub 15921cb0ef41Sopenharmony_ci VisitWord32TruncatingBinop<T>(node); 15931cb0ef41Sopenharmony_ci if (lower<T>()) ChangeToPureOp(node, Int32Op(node)); 15941cb0ef41Sopenharmony_ci return; 15951cb0ef41Sopenharmony_ci } 15961cb0ef41Sopenharmony_ci } 15971cb0ef41Sopenharmony_ci 15981cb0ef41Sopenharmony_ci // Try to use type feedback. 15991cb0ef41Sopenharmony_ci NumberOperationHint const hint = NumberOperationHint::kSignedSmall; 16001cb0ef41Sopenharmony_ci DCHECK_EQ(hint, NumberOperationHintOf(node->op())); 16011cb0ef41Sopenharmony_ci 16021cb0ef41Sopenharmony_ci Type left_feedback_type = TypeOf(node->InputAt(0)); 16031cb0ef41Sopenharmony_ci Type right_feedback_type = TypeOf(node->InputAt(1)); 16041cb0ef41Sopenharmony_ci 16051cb0ef41Sopenharmony_ci // Using Signed32 as restriction type amounts to promising there won't be 16061cb0ef41Sopenharmony_ci // signed overflow. This is incompatible with relying on a Word32 truncation 16071cb0ef41Sopenharmony_ci // in order to skip the overflow check. Similarly, we must not drop -0 from 16081cb0ef41Sopenharmony_ci // the result type unless we deopt for -0 inputs. 16091cb0ef41Sopenharmony_ci Type const restriction = 16101cb0ef41Sopenharmony_ci truncation.IsUsedAsWord32() 16111cb0ef41Sopenharmony_ci ? Type::Any() 16121cb0ef41Sopenharmony_ci : (truncation.identify_zeros() == kIdentifyZeros) 16131cb0ef41Sopenharmony_ci ? Type::Signed32OrMinusZero() 16141cb0ef41Sopenharmony_ci : Type::Signed32(); 16151cb0ef41Sopenharmony_ci 16161cb0ef41Sopenharmony_ci // Handle the case when no int32 checks on inputs are necessary (but 16171cb0ef41Sopenharmony_ci // an overflow check is needed on the output). Note that we do not 16181cb0ef41Sopenharmony_ci // have to do any check if at most one side can be minus zero. For 16191cb0ef41Sopenharmony_ci // subtraction we need to handle the case of -0 - 0 properly, since 16201cb0ef41Sopenharmony_ci // that can produce -0. 16211cb0ef41Sopenharmony_ci Type left_constraint_type = 16221cb0ef41Sopenharmony_ci node->opcode() == IrOpcode::kSpeculativeSafeIntegerAdd 16231cb0ef41Sopenharmony_ci ? Type::Signed32OrMinusZero() 16241cb0ef41Sopenharmony_ci : Type::Signed32(); 16251cb0ef41Sopenharmony_ci if (left_upper.Is(left_constraint_type) && 16261cb0ef41Sopenharmony_ci right_upper.Is(Type::Signed32OrMinusZero()) && 16271cb0ef41Sopenharmony_ci (left_upper.Is(Type::Signed32()) || right_upper.Is(Type::Signed32()))) { 16281cb0ef41Sopenharmony_ci VisitBinop<T>(node, UseInfo::TruncatingWord32(), 16291cb0ef41Sopenharmony_ci MachineRepresentation::kWord32, restriction); 16301cb0ef41Sopenharmony_ci } else { 16311cb0ef41Sopenharmony_ci // If the output's truncation is identify-zeros, we can pass it 16321cb0ef41Sopenharmony_ci // along. Moreover, if the operation is addition and we know the 16331cb0ef41Sopenharmony_ci // right-hand side is not minus zero, we do not have to distinguish 16341cb0ef41Sopenharmony_ci // between 0 and -0. 16351cb0ef41Sopenharmony_ci IdentifyZeros left_identify_zeros = truncation.identify_zeros(); 16361cb0ef41Sopenharmony_ci if (node->opcode() == IrOpcode::kSpeculativeSafeIntegerAdd && 16371cb0ef41Sopenharmony_ci !right_feedback_type.Maybe(Type::MinusZero())) { 16381cb0ef41Sopenharmony_ci left_identify_zeros = kIdentifyZeros; 16391cb0ef41Sopenharmony_ci } 16401cb0ef41Sopenharmony_ci UseInfo left_use = 16411cb0ef41Sopenharmony_ci CheckedUseInfoAsWord32FromHint(hint, left_identify_zeros); 16421cb0ef41Sopenharmony_ci // For CheckedInt32Add and CheckedInt32Sub, we don't need to do 16431cb0ef41Sopenharmony_ci // a minus zero check for the right hand side, since we already 16441cb0ef41Sopenharmony_ci // know that the left hand side is a proper Signed32 value, 16451cb0ef41Sopenharmony_ci // potentially guarded by a check. 16461cb0ef41Sopenharmony_ci UseInfo right_use = CheckedUseInfoAsWord32FromHint(hint, kIdentifyZeros); 16471cb0ef41Sopenharmony_ci VisitBinop<T>(node, left_use, right_use, MachineRepresentation::kWord32, 16481cb0ef41Sopenharmony_ci restriction); 16491cb0ef41Sopenharmony_ci } 16501cb0ef41Sopenharmony_ci 16511cb0ef41Sopenharmony_ci if (lower<T>()) { 16521cb0ef41Sopenharmony_ci if (truncation.IsUsedAsWord32() || 16531cb0ef41Sopenharmony_ci !CanOverflowSigned32(node->op(), left_feedback_type, 16541cb0ef41Sopenharmony_ci right_feedback_type, type_cache_, 16551cb0ef41Sopenharmony_ci graph_zone())) { 16561cb0ef41Sopenharmony_ci ChangeToPureOp(node, Int32Op(node)); 16571cb0ef41Sopenharmony_ci } else { 16581cb0ef41Sopenharmony_ci ChangeToInt32OverflowOp(node); 16591cb0ef41Sopenharmony_ci } 16601cb0ef41Sopenharmony_ci } 16611cb0ef41Sopenharmony_ci return; 16621cb0ef41Sopenharmony_ci } 16631cb0ef41Sopenharmony_ci 16641cb0ef41Sopenharmony_ci template <Phase T> 16651cb0ef41Sopenharmony_ci void VisitSpeculativeAdditiveOp(Node* node, Truncation truncation, 16661cb0ef41Sopenharmony_ci SimplifiedLowering* lowering) { 16671cb0ef41Sopenharmony_ci if (BothInputsAre(node, type_cache_->kAdditiveSafeIntegerOrMinusZero) && 16681cb0ef41Sopenharmony_ci (GetUpperBound(node).Is(Type::Signed32()) || 16691cb0ef41Sopenharmony_ci GetUpperBound(node).Is(Type::Unsigned32()) || 16701cb0ef41Sopenharmony_ci truncation.IsUsedAsWord32())) { 16711cb0ef41Sopenharmony_ci // => Int32Add/Sub 16721cb0ef41Sopenharmony_ci VisitWord32TruncatingBinop<T>(node); 16731cb0ef41Sopenharmony_ci if (lower<T>()) ChangeToPureOp(node, Int32Op(node)); 16741cb0ef41Sopenharmony_ci return; 16751cb0ef41Sopenharmony_ci } 16761cb0ef41Sopenharmony_ci 16771cb0ef41Sopenharmony_ci // default case => Float64Add/Sub 16781cb0ef41Sopenharmony_ci VisitBinop<T>(node, 16791cb0ef41Sopenharmony_ci UseInfo::CheckedNumberOrOddballAsFloat64(kDistinguishZeros, 16801cb0ef41Sopenharmony_ci FeedbackSource()), 16811cb0ef41Sopenharmony_ci MachineRepresentation::kFloat64, Type::Number()); 16821cb0ef41Sopenharmony_ci if (lower<T>()) { 16831cb0ef41Sopenharmony_ci ChangeToPureOp(node, Float64Op(node)); 16841cb0ef41Sopenharmony_ci } 16851cb0ef41Sopenharmony_ci return; 16861cb0ef41Sopenharmony_ci } 16871cb0ef41Sopenharmony_ci 16881cb0ef41Sopenharmony_ci template <Phase T> 16891cb0ef41Sopenharmony_ci void VisitSpeculativeNumberModulus(Node* node, Truncation truncation, 16901cb0ef41Sopenharmony_ci SimplifiedLowering* lowering) { 16911cb0ef41Sopenharmony_ci if (BothInputsAre(node, Type::Unsigned32OrMinusZeroOrNaN()) && 16921cb0ef41Sopenharmony_ci (truncation.IsUsedAsWord32() || 16931cb0ef41Sopenharmony_ci NodeProperties::GetType(node).Is(Type::Unsigned32()))) { 16941cb0ef41Sopenharmony_ci // => unsigned Uint32Mod 16951cb0ef41Sopenharmony_ci VisitWord32TruncatingBinop<T>(node); 16961cb0ef41Sopenharmony_ci if (lower<T>()) DeferReplacement(node, lowering->Uint32Mod(node)); 16971cb0ef41Sopenharmony_ci return; 16981cb0ef41Sopenharmony_ci } 16991cb0ef41Sopenharmony_ci if (BothInputsAre(node, Type::Signed32OrMinusZeroOrNaN()) && 17001cb0ef41Sopenharmony_ci (truncation.IsUsedAsWord32() || 17011cb0ef41Sopenharmony_ci NodeProperties::GetType(node).Is(Type::Signed32()))) { 17021cb0ef41Sopenharmony_ci // => signed Int32Mod 17031cb0ef41Sopenharmony_ci VisitWord32TruncatingBinop<T>(node); 17041cb0ef41Sopenharmony_ci if (lower<T>()) DeferReplacement(node, lowering->Int32Mod(node)); 17051cb0ef41Sopenharmony_ci return; 17061cb0ef41Sopenharmony_ci } 17071cb0ef41Sopenharmony_ci 17081cb0ef41Sopenharmony_ci // Try to use type feedback. 17091cb0ef41Sopenharmony_ci NumberOperationHint hint = NumberOperationHintOf(node->op()); 17101cb0ef41Sopenharmony_ci 17111cb0ef41Sopenharmony_ci // Handle the case when no uint32 checks on inputs are necessary 17121cb0ef41Sopenharmony_ci // (but an overflow check is needed on the output). 17131cb0ef41Sopenharmony_ci if (BothInputsAreUnsigned32(node)) { 17141cb0ef41Sopenharmony_ci if (hint == NumberOperationHint::kSignedSmall) { 17151cb0ef41Sopenharmony_ci VisitBinop<T>(node, UseInfo::TruncatingWord32(), 17161cb0ef41Sopenharmony_ci MachineRepresentation::kWord32, Type::Unsigned32()); 17171cb0ef41Sopenharmony_ci if (lower<T>()) ChangeToUint32OverflowOp(node); 17181cb0ef41Sopenharmony_ci return; 17191cb0ef41Sopenharmony_ci } 17201cb0ef41Sopenharmony_ci } 17211cb0ef41Sopenharmony_ci 17221cb0ef41Sopenharmony_ci // Handle the case when no int32 checks on inputs are necessary 17231cb0ef41Sopenharmony_ci // (but an overflow check is needed on the output). 17241cb0ef41Sopenharmony_ci if (BothInputsAre(node, Type::Signed32())) { 17251cb0ef41Sopenharmony_ci // If both the inputs the feedback are int32, use the overflow op. 17261cb0ef41Sopenharmony_ci if (hint == NumberOperationHint::kSignedSmall) { 17271cb0ef41Sopenharmony_ci VisitBinop<T>(node, UseInfo::TruncatingWord32(), 17281cb0ef41Sopenharmony_ci MachineRepresentation::kWord32, Type::Signed32()); 17291cb0ef41Sopenharmony_ci if (lower<T>()) ChangeToInt32OverflowOp(node); 17301cb0ef41Sopenharmony_ci return; 17311cb0ef41Sopenharmony_ci } 17321cb0ef41Sopenharmony_ci } 17331cb0ef41Sopenharmony_ci 17341cb0ef41Sopenharmony_ci if (hint == NumberOperationHint::kSignedSmall) { 17351cb0ef41Sopenharmony_ci // If the result is truncated, we only need to check the inputs. 17361cb0ef41Sopenharmony_ci // For the left hand side we just propagate the identify zeros 17371cb0ef41Sopenharmony_ci // mode of the {truncation}; and for modulus the sign of the 17381cb0ef41Sopenharmony_ci // right hand side doesn't matter anyways, so in particular there's 17391cb0ef41Sopenharmony_ci // no observable difference between a 0 and a -0 then. 17401cb0ef41Sopenharmony_ci UseInfo const lhs_use = 17411cb0ef41Sopenharmony_ci CheckedUseInfoAsWord32FromHint(hint, truncation.identify_zeros()); 17421cb0ef41Sopenharmony_ci UseInfo const rhs_use = 17431cb0ef41Sopenharmony_ci CheckedUseInfoAsWord32FromHint(hint, kIdentifyZeros); 17441cb0ef41Sopenharmony_ci if (truncation.IsUsedAsWord32()) { 17451cb0ef41Sopenharmony_ci VisitBinop<T>(node, lhs_use, rhs_use, MachineRepresentation::kWord32); 17461cb0ef41Sopenharmony_ci if (lower<T>()) DeferReplacement(node, lowering->Int32Mod(node)); 17471cb0ef41Sopenharmony_ci } else if (BothInputsAre(node, Type::Unsigned32OrMinusZeroOrNaN())) { 17481cb0ef41Sopenharmony_ci Type const restriction = 17491cb0ef41Sopenharmony_ci truncation.IdentifiesZeroAndMinusZero() && 17501cb0ef41Sopenharmony_ci TypeOf(node->InputAt(0)).Maybe(Type::MinusZero()) 17511cb0ef41Sopenharmony_ci ? Type::Unsigned32OrMinusZero() 17521cb0ef41Sopenharmony_ci : Type::Unsigned32(); 17531cb0ef41Sopenharmony_ci VisitBinop<T>(node, lhs_use, rhs_use, MachineRepresentation::kWord32, 17541cb0ef41Sopenharmony_ci restriction); 17551cb0ef41Sopenharmony_ci if (lower<T>()) ChangeToUint32OverflowOp(node); 17561cb0ef41Sopenharmony_ci } else { 17571cb0ef41Sopenharmony_ci Type const restriction = 17581cb0ef41Sopenharmony_ci truncation.IdentifiesZeroAndMinusZero() && 17591cb0ef41Sopenharmony_ci TypeOf(node->InputAt(0)).Maybe(Type::MinusZero()) 17601cb0ef41Sopenharmony_ci ? Type::Signed32OrMinusZero() 17611cb0ef41Sopenharmony_ci : Type::Signed32(); 17621cb0ef41Sopenharmony_ci VisitBinop<T>(node, lhs_use, rhs_use, MachineRepresentation::kWord32, 17631cb0ef41Sopenharmony_ci restriction); 17641cb0ef41Sopenharmony_ci if (lower<T>()) ChangeToInt32OverflowOp(node); 17651cb0ef41Sopenharmony_ci } 17661cb0ef41Sopenharmony_ci return; 17671cb0ef41Sopenharmony_ci } 17681cb0ef41Sopenharmony_ci 17691cb0ef41Sopenharmony_ci if (TypeOf(node->InputAt(0)).Is(Type::Unsigned32()) && 17701cb0ef41Sopenharmony_ci TypeOf(node->InputAt(1)).Is(Type::Unsigned32()) && 17711cb0ef41Sopenharmony_ci (truncation.IsUsedAsWord32() || 17721cb0ef41Sopenharmony_ci NodeProperties::GetType(node).Is(Type::Unsigned32()))) { 17731cb0ef41Sopenharmony_ci VisitBinop<T>(node, UseInfo::TruncatingWord32(), 17741cb0ef41Sopenharmony_ci MachineRepresentation::kWord32, Type::Number()); 17751cb0ef41Sopenharmony_ci if (lower<T>()) DeferReplacement(node, lowering->Uint32Mod(node)); 17761cb0ef41Sopenharmony_ci return; 17771cb0ef41Sopenharmony_ci } 17781cb0ef41Sopenharmony_ci if (TypeOf(node->InputAt(0)).Is(Type::Signed32()) && 17791cb0ef41Sopenharmony_ci TypeOf(node->InputAt(1)).Is(Type::Signed32()) && 17801cb0ef41Sopenharmony_ci (truncation.IsUsedAsWord32() || 17811cb0ef41Sopenharmony_ci NodeProperties::GetType(node).Is(Type::Signed32()))) { 17821cb0ef41Sopenharmony_ci VisitBinop<T>(node, UseInfo::TruncatingWord32(), 17831cb0ef41Sopenharmony_ci MachineRepresentation::kWord32, Type::Number()); 17841cb0ef41Sopenharmony_ci if (lower<T>()) DeferReplacement(node, lowering->Int32Mod(node)); 17851cb0ef41Sopenharmony_ci return; 17861cb0ef41Sopenharmony_ci } 17871cb0ef41Sopenharmony_ci 17881cb0ef41Sopenharmony_ci // default case => Float64Mod 17891cb0ef41Sopenharmony_ci // For the left hand side we just propagate the identify zeros 17901cb0ef41Sopenharmony_ci // mode of the {truncation}; and for modulus the sign of the 17911cb0ef41Sopenharmony_ci // right hand side doesn't matter anyways, so in particular there's 17921cb0ef41Sopenharmony_ci // no observable difference between a 0 and a -0 then. 17931cb0ef41Sopenharmony_ci UseInfo const lhs_use = UseInfo::CheckedNumberOrOddballAsFloat64( 17941cb0ef41Sopenharmony_ci truncation.identify_zeros(), FeedbackSource()); 17951cb0ef41Sopenharmony_ci UseInfo const rhs_use = UseInfo::CheckedNumberOrOddballAsFloat64( 17961cb0ef41Sopenharmony_ci kIdentifyZeros, FeedbackSource()); 17971cb0ef41Sopenharmony_ci VisitBinop<T>(node, lhs_use, rhs_use, MachineRepresentation::kFloat64, 17981cb0ef41Sopenharmony_ci Type::Number()); 17991cb0ef41Sopenharmony_ci if (lower<T>()) ChangeToPureOp(node, Float64Op(node)); 18001cb0ef41Sopenharmony_ci return; 18011cb0ef41Sopenharmony_ci } 18021cb0ef41Sopenharmony_ci 18031cb0ef41Sopenharmony_ci // Just assert for Propagate and Retype. Lower specialized below. 18041cb0ef41Sopenharmony_ci template <Phase T> 18051cb0ef41Sopenharmony_ci void InsertUnreachableIfNecessary(Node* node) { 18061cb0ef41Sopenharmony_ci static_assert(propagate<T>() || retype<T>(), 18071cb0ef41Sopenharmony_ci "This version of InsertUnreachableIfNecessary has to be " 18081cb0ef41Sopenharmony_ci "called in the Propagate or Retype phase."); 18091cb0ef41Sopenharmony_ci } 18101cb0ef41Sopenharmony_ci 18111cb0ef41Sopenharmony_ci template <Phase T> 18121cb0ef41Sopenharmony_ci void VisitCheckBounds(Node* node, SimplifiedLowering* lowering) { 18131cb0ef41Sopenharmony_ci CheckBoundsParameters const& p = CheckBoundsParametersOf(node->op()); 18141cb0ef41Sopenharmony_ci FeedbackSource const& feedback = p.check_parameters().feedback(); 18151cb0ef41Sopenharmony_ci Type const index_type = TypeOf(node->InputAt(0)); 18161cb0ef41Sopenharmony_ci Type const length_type = TypeOf(node->InputAt(1)); 18171cb0ef41Sopenharmony_ci 18181cb0ef41Sopenharmony_ci // Conversions, if requested and needed, will be handled by the 18191cb0ef41Sopenharmony_ci // representation changer, not by the lower-level Checked*Bounds operators. 18201cb0ef41Sopenharmony_ci CheckBoundsFlags new_flags = 18211cb0ef41Sopenharmony_ci p.flags().without(CheckBoundsFlag::kConvertStringAndMinusZero); 18221cb0ef41Sopenharmony_ci 18231cb0ef41Sopenharmony_ci if (length_type.Is(Type::Unsigned31())) { 18241cb0ef41Sopenharmony_ci if (index_type.Is(Type::Integral32()) || 18251cb0ef41Sopenharmony_ci (index_type.Is(Type::Integral32OrMinusZero()) && 18261cb0ef41Sopenharmony_ci p.flags() & CheckBoundsFlag::kConvertStringAndMinusZero)) { 18271cb0ef41Sopenharmony_ci // Map the values in the [-2^31,-1] range to the [2^31,2^32-1] range, 18281cb0ef41Sopenharmony_ci // which will be considered out-of-bounds because the {length_type} is 18291cb0ef41Sopenharmony_ci // limited to Unsigned31. This also converts -0 to 0. 18301cb0ef41Sopenharmony_ci VisitBinop<T>(node, UseInfo::TruncatingWord32(), 18311cb0ef41Sopenharmony_ci MachineRepresentation::kWord32); 18321cb0ef41Sopenharmony_ci if (lower<T>()) { 18331cb0ef41Sopenharmony_ci if (index_type.IsNone() || length_type.IsNone() || 18341cb0ef41Sopenharmony_ci (index_type.Min() >= 0.0 && 18351cb0ef41Sopenharmony_ci index_type.Max() < length_type.Min())) { 18361cb0ef41Sopenharmony_ci // The bounds check is redundant if we already know that 18371cb0ef41Sopenharmony_ci // the index is within the bounds of [0.0, length[. 18381cb0ef41Sopenharmony_ci // TODO(neis): Move this into TypedOptimization? 18391cb0ef41Sopenharmony_ci new_flags |= CheckBoundsFlag::kAbortOnOutOfBounds; 18401cb0ef41Sopenharmony_ci } 18411cb0ef41Sopenharmony_ci ChangeOp(node, 18421cb0ef41Sopenharmony_ci simplified()->CheckedUint32Bounds(feedback, new_flags)); 18431cb0ef41Sopenharmony_ci } 18441cb0ef41Sopenharmony_ci } else if (p.flags() & CheckBoundsFlag::kConvertStringAndMinusZero) { 18451cb0ef41Sopenharmony_ci VisitBinop<T>(node, UseInfo::CheckedTaggedAsArrayIndex(feedback), 18461cb0ef41Sopenharmony_ci UseInfo::Word(), MachineType::PointerRepresentation()); 18471cb0ef41Sopenharmony_ci if (lower<T>()) { 18481cb0ef41Sopenharmony_ci if (jsgraph_->machine()->Is64()) { 18491cb0ef41Sopenharmony_ci ChangeOp(node, 18501cb0ef41Sopenharmony_ci simplified()->CheckedUint64Bounds(feedback, new_flags)); 18511cb0ef41Sopenharmony_ci } else { 18521cb0ef41Sopenharmony_ci ChangeOp(node, 18531cb0ef41Sopenharmony_ci simplified()->CheckedUint32Bounds(feedback, new_flags)); 18541cb0ef41Sopenharmony_ci } 18551cb0ef41Sopenharmony_ci } 18561cb0ef41Sopenharmony_ci } else { 18571cb0ef41Sopenharmony_ci VisitBinop<T>( 18581cb0ef41Sopenharmony_ci node, UseInfo::CheckedSigned32AsWord32(kDistinguishZeros, feedback), 18591cb0ef41Sopenharmony_ci UseInfo::TruncatingWord32(), MachineRepresentation::kWord32); 18601cb0ef41Sopenharmony_ci if (lower<T>()) { 18611cb0ef41Sopenharmony_ci ChangeOp(node, 18621cb0ef41Sopenharmony_ci simplified()->CheckedUint32Bounds(feedback, new_flags)); 18631cb0ef41Sopenharmony_ci } 18641cb0ef41Sopenharmony_ci } 18651cb0ef41Sopenharmony_ci } else { 18661cb0ef41Sopenharmony_ci CHECK(length_type.Is(type_cache_->kPositiveSafeInteger)); 18671cb0ef41Sopenharmony_ci IdentifyZeros zero_handling = 18681cb0ef41Sopenharmony_ci (p.flags() & CheckBoundsFlag::kConvertStringAndMinusZero) 18691cb0ef41Sopenharmony_ci ? kIdentifyZeros 18701cb0ef41Sopenharmony_ci : kDistinguishZeros; 18711cb0ef41Sopenharmony_ci VisitBinop<T>(node, 18721cb0ef41Sopenharmony_ci UseInfo::CheckedSigned64AsWord64(zero_handling, feedback), 18731cb0ef41Sopenharmony_ci UseInfo::Word64(), MachineRepresentation::kWord64); 18741cb0ef41Sopenharmony_ci if (lower<T>()) { 18751cb0ef41Sopenharmony_ci ChangeOp(node, simplified()->CheckedUint64Bounds(feedback, new_flags)); 18761cb0ef41Sopenharmony_ci } 18771cb0ef41Sopenharmony_ci } 18781cb0ef41Sopenharmony_ci } 18791cb0ef41Sopenharmony_ci 18801cb0ef41Sopenharmony_ci UseInfo UseInfoForFastApiCallArgument(CTypeInfo type, 18811cb0ef41Sopenharmony_ci FeedbackSource const& feedback) { 18821cb0ef41Sopenharmony_ci switch (type.GetSequenceType()) { 18831cb0ef41Sopenharmony_ci case CTypeInfo::SequenceType::kScalar: { 18841cb0ef41Sopenharmony_ci switch (type.GetType()) { 18851cb0ef41Sopenharmony_ci case CTypeInfo::Type::kVoid: 18861cb0ef41Sopenharmony_ci UNREACHABLE(); 18871cb0ef41Sopenharmony_ci case CTypeInfo::Type::kBool: 18881cb0ef41Sopenharmony_ci return UseInfo::Bool(); 18891cb0ef41Sopenharmony_ci case CTypeInfo::Type::kInt32: 18901cb0ef41Sopenharmony_ci case CTypeInfo::Type::kUint32: 18911cb0ef41Sopenharmony_ci return UseInfo::CheckedNumberAsWord32(feedback); 18921cb0ef41Sopenharmony_ci // TODO(mslekova): We deopt for unsafe integers, but ultimately we 18931cb0ef41Sopenharmony_ci // want to make this less restrictive in order to stay on the fast 18941cb0ef41Sopenharmony_ci // path. 18951cb0ef41Sopenharmony_ci case CTypeInfo::Type::kInt64: 18961cb0ef41Sopenharmony_ci case CTypeInfo::Type::kUint64: 18971cb0ef41Sopenharmony_ci case CTypeInfo::Type::kAny: 18981cb0ef41Sopenharmony_ci return UseInfo::CheckedSigned64AsWord64(kIdentifyZeros, feedback); 18991cb0ef41Sopenharmony_ci case CTypeInfo::Type::kFloat32: 19001cb0ef41Sopenharmony_ci case CTypeInfo::Type::kFloat64: 19011cb0ef41Sopenharmony_ci return UseInfo::CheckedNumberAsFloat64(kDistinguishZeros, feedback); 19021cb0ef41Sopenharmony_ci case CTypeInfo::Type::kV8Value: 19031cb0ef41Sopenharmony_ci case CTypeInfo::Type::kApiObject: 19041cb0ef41Sopenharmony_ci return UseInfo::AnyTagged(); 19051cb0ef41Sopenharmony_ci } 19061cb0ef41Sopenharmony_ci } 19071cb0ef41Sopenharmony_ci case CTypeInfo::SequenceType::kIsSequence: { 19081cb0ef41Sopenharmony_ci CHECK_EQ(type.GetType(), CTypeInfo::Type::kVoid); 19091cb0ef41Sopenharmony_ci return UseInfo::AnyTagged(); 19101cb0ef41Sopenharmony_ci } 19111cb0ef41Sopenharmony_ci case CTypeInfo::SequenceType::kIsTypedArray: { 19121cb0ef41Sopenharmony_ci return UseInfo::AnyTagged(); 19131cb0ef41Sopenharmony_ci } 19141cb0ef41Sopenharmony_ci default: { 19151cb0ef41Sopenharmony_ci UNREACHABLE(); // TODO(mslekova): Implement array buffers. 19161cb0ef41Sopenharmony_ci } 19171cb0ef41Sopenharmony_ci } 19181cb0ef41Sopenharmony_ci } 19191cb0ef41Sopenharmony_ci 19201cb0ef41Sopenharmony_ci static constexpr int kInitialArgumentsCount = 10; 19211cb0ef41Sopenharmony_ci 19221cb0ef41Sopenharmony_ci template <Phase T> 19231cb0ef41Sopenharmony_ci void VisitFastApiCall(Node* node, SimplifiedLowering* lowering) { 19241cb0ef41Sopenharmony_ci FastApiCallParameters const& op_params = 19251cb0ef41Sopenharmony_ci FastApiCallParametersOf(node->op()); 19261cb0ef41Sopenharmony_ci // We only consider the first function signature here. In case of function 19271cb0ef41Sopenharmony_ci // overloads, we only support the case of two functions that differ for one 19281cb0ef41Sopenharmony_ci // argument, which must be a JSArray in one function and a TypedArray in the 19291cb0ef41Sopenharmony_ci // other function, and both JSArrays and TypedArrays have the same UseInfo 19301cb0ef41Sopenharmony_ci // UseInfo::AnyTagged(). All the other argument types must match. 19311cb0ef41Sopenharmony_ci const CFunctionInfo* c_signature = op_params.c_functions()[0].signature; 19321cb0ef41Sopenharmony_ci const int c_arg_count = c_signature->ArgumentCount(); 19331cb0ef41Sopenharmony_ci CallDescriptor* call_descriptor = op_params.descriptor(); 19341cb0ef41Sopenharmony_ci int js_arg_count = static_cast<int>(call_descriptor->ParameterCount()); 19351cb0ef41Sopenharmony_ci const int value_input_count = node->op()->ValueInputCount(); 19361cb0ef41Sopenharmony_ci CHECK_EQ(FastApiCallNode::ArityForArgc(c_arg_count, js_arg_count), 19371cb0ef41Sopenharmony_ci value_input_count); 19381cb0ef41Sopenharmony_ci 19391cb0ef41Sopenharmony_ci base::SmallVector<UseInfo, kInitialArgumentsCount> arg_use_info( 19401cb0ef41Sopenharmony_ci c_arg_count); 19411cb0ef41Sopenharmony_ci // Propagate representation information from TypeInfo. 19421cb0ef41Sopenharmony_ci for (int i = 0; i < c_arg_count; i++) { 19431cb0ef41Sopenharmony_ci arg_use_info[i] = UseInfoForFastApiCallArgument( 19441cb0ef41Sopenharmony_ci c_signature->ArgumentInfo(i), op_params.feedback()); 19451cb0ef41Sopenharmony_ci ProcessInput<T>(node, i, arg_use_info[i]); 19461cb0ef41Sopenharmony_ci } 19471cb0ef41Sopenharmony_ci 19481cb0ef41Sopenharmony_ci // The call code for the slow call. 19491cb0ef41Sopenharmony_ci ProcessInput<T>(node, c_arg_count, UseInfo::AnyTagged()); 19501cb0ef41Sopenharmony_ci for (int i = 1; i <= js_arg_count; i++) { 19511cb0ef41Sopenharmony_ci ProcessInput<T>(node, c_arg_count + i, 19521cb0ef41Sopenharmony_ci TruncatingUseInfoFromRepresentation( 19531cb0ef41Sopenharmony_ci call_descriptor->GetInputType(i).representation())); 19541cb0ef41Sopenharmony_ci } 19551cb0ef41Sopenharmony_ci for (int i = c_arg_count + js_arg_count; i < value_input_count; ++i) { 19561cb0ef41Sopenharmony_ci ProcessInput<T>(node, i, UseInfo::AnyTagged()); 19571cb0ef41Sopenharmony_ci } 19581cb0ef41Sopenharmony_ci ProcessRemainingInputs<T>(node, value_input_count); 19591cb0ef41Sopenharmony_ci SetOutput<T>(node, MachineRepresentation::kTagged); 19601cb0ef41Sopenharmony_ci } 19611cb0ef41Sopenharmony_ci 19621cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY 19631cb0ef41Sopenharmony_ci static MachineType MachineTypeForWasmReturnType(wasm::ValueType type) { 19641cb0ef41Sopenharmony_ci switch (type.kind()) { 19651cb0ef41Sopenharmony_ci case wasm::kI32: 19661cb0ef41Sopenharmony_ci return MachineType::Int32(); 19671cb0ef41Sopenharmony_ci case wasm::kF32: 19681cb0ef41Sopenharmony_ci return MachineType::Float32(); 19691cb0ef41Sopenharmony_ci case wasm::kF64: 19701cb0ef41Sopenharmony_ci return MachineType::Float64(); 19711cb0ef41Sopenharmony_ci case wasm::kI64: 19721cb0ef41Sopenharmony_ci // Not used for i64, see VisitJSWasmCall(). 19731cb0ef41Sopenharmony_ci default: 19741cb0ef41Sopenharmony_ci UNREACHABLE(); 19751cb0ef41Sopenharmony_ci } 19761cb0ef41Sopenharmony_ci } 19771cb0ef41Sopenharmony_ci 19781cb0ef41Sopenharmony_ci UseInfo UseInfoForJSWasmCallArgument(Node* input, wasm::ValueType type, 19791cb0ef41Sopenharmony_ci FeedbackSource const& feedback) { 19801cb0ef41Sopenharmony_ci // If the input type is a Number or Oddball, we can directly convert the 19811cb0ef41Sopenharmony_ci // input into the Wasm native type of the argument. If not, we return 19821cb0ef41Sopenharmony_ci // UseInfo::AnyTagged to signal that WasmWrapperGraphBuilder will need to 19831cb0ef41Sopenharmony_ci // add Nodes to perform the conversion (in WasmWrapperGraphBuilder::FromJS). 19841cb0ef41Sopenharmony_ci switch (type.kind()) { 19851cb0ef41Sopenharmony_ci case wasm::kI32: 19861cb0ef41Sopenharmony_ci return UseInfo::CheckedNumberOrOddballAsWord32(feedback); 19871cb0ef41Sopenharmony_ci case wasm::kI64: 19881cb0ef41Sopenharmony_ci return UseInfo::AnyTagged(); 19891cb0ef41Sopenharmony_ci case wasm::kF32: 19901cb0ef41Sopenharmony_ci case wasm::kF64: 19911cb0ef41Sopenharmony_ci // For Float32, TruncateFloat64ToFloat32 will be inserted later in 19921cb0ef41Sopenharmony_ci // WasmWrapperGraphBuilder::BuildJSToWasmWrapper. 19931cb0ef41Sopenharmony_ci return UseInfo::CheckedNumberOrOddballAsFloat64(kDistinguishZeros, 19941cb0ef41Sopenharmony_ci feedback); 19951cb0ef41Sopenharmony_ci default: 19961cb0ef41Sopenharmony_ci UNREACHABLE(); 19971cb0ef41Sopenharmony_ci } 19981cb0ef41Sopenharmony_ci } 19991cb0ef41Sopenharmony_ci 20001cb0ef41Sopenharmony_ci template <Phase T> 20011cb0ef41Sopenharmony_ci void VisitJSWasmCall(Node* node, SimplifiedLowering* lowering) { 20021cb0ef41Sopenharmony_ci DCHECK_EQ(JSWasmCallNode::TargetIndex(), 0); 20031cb0ef41Sopenharmony_ci DCHECK_EQ(JSWasmCallNode::ReceiverIndex(), 1); 20041cb0ef41Sopenharmony_ci DCHECK_EQ(JSWasmCallNode::FirstArgumentIndex(), 2); 20051cb0ef41Sopenharmony_ci 20061cb0ef41Sopenharmony_ci JSWasmCallNode n(node); 20071cb0ef41Sopenharmony_ci 20081cb0ef41Sopenharmony_ci JSWasmCallParameters const& params = n.Parameters(); 20091cb0ef41Sopenharmony_ci const wasm::FunctionSig* wasm_signature = params.signature(); 20101cb0ef41Sopenharmony_ci int wasm_arg_count = static_cast<int>(wasm_signature->parameter_count()); 20111cb0ef41Sopenharmony_ci DCHECK_EQ(wasm_arg_count, n.ArgumentCount()); 20121cb0ef41Sopenharmony_ci 20131cb0ef41Sopenharmony_ci base::SmallVector<UseInfo, kInitialArgumentsCount> arg_use_info( 20141cb0ef41Sopenharmony_ci wasm_arg_count); 20151cb0ef41Sopenharmony_ci 20161cb0ef41Sopenharmony_ci // Visit JSFunction and Receiver nodes. 20171cb0ef41Sopenharmony_ci ProcessInput<T>(node, JSWasmCallNode::TargetIndex(), UseInfo::Any()); 20181cb0ef41Sopenharmony_ci ProcessInput<T>(node, JSWasmCallNode::ReceiverIndex(), UseInfo::Any()); 20191cb0ef41Sopenharmony_ci 20201cb0ef41Sopenharmony_ci // Propagate representation information from TypeInfo. 20211cb0ef41Sopenharmony_ci for (int i = 0; i < wasm_arg_count; i++) { 20221cb0ef41Sopenharmony_ci TNode<Object> input = n.Argument(i); 20231cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(input); 20241cb0ef41Sopenharmony_ci arg_use_info[i] = UseInfoForJSWasmCallArgument( 20251cb0ef41Sopenharmony_ci input, wasm_signature->GetParam(i), params.feedback()); 20261cb0ef41Sopenharmony_ci ProcessInput<T>(node, JSWasmCallNode::ArgumentIndex(i), arg_use_info[i]); 20271cb0ef41Sopenharmony_ci } 20281cb0ef41Sopenharmony_ci 20291cb0ef41Sopenharmony_ci // Visit value, context and frame state inputs as tagged. 20301cb0ef41Sopenharmony_ci int first_effect_index = NodeProperties::FirstEffectIndex(node); 20311cb0ef41Sopenharmony_ci DCHECK(first_effect_index > 20321cb0ef41Sopenharmony_ci JSWasmCallNode::FirstArgumentIndex() + wasm_arg_count); 20331cb0ef41Sopenharmony_ci for (int i = JSWasmCallNode::FirstArgumentIndex() + wasm_arg_count; 20341cb0ef41Sopenharmony_ci i < first_effect_index; i++) { 20351cb0ef41Sopenharmony_ci ProcessInput<T>(node, i, UseInfo::AnyTagged()); 20361cb0ef41Sopenharmony_ci } 20371cb0ef41Sopenharmony_ci 20381cb0ef41Sopenharmony_ci // Effect and Control. 20391cb0ef41Sopenharmony_ci ProcessRemainingInputs<T>(node, NodeProperties::FirstEffectIndex(node)); 20401cb0ef41Sopenharmony_ci 20411cb0ef41Sopenharmony_ci if (wasm_signature->return_count() == 1) { 20421cb0ef41Sopenharmony_ci if (wasm_signature->GetReturn().kind() == wasm::kI64) { 20431cb0ef41Sopenharmony_ci // Conversion between negative int64 and BigInt not supported yet. 20441cb0ef41Sopenharmony_ci // Do not bypass the type conversion when the result type is i64. 20451cb0ef41Sopenharmony_ci SetOutput<T>(node, MachineRepresentation::kTagged); 20461cb0ef41Sopenharmony_ci } else { 20471cb0ef41Sopenharmony_ci MachineType return_type = 20481cb0ef41Sopenharmony_ci MachineTypeForWasmReturnType(wasm_signature->GetReturn()); 20491cb0ef41Sopenharmony_ci SetOutput<T>( 20501cb0ef41Sopenharmony_ci node, return_type.representation(), 20511cb0ef41Sopenharmony_ci JSWasmCallNode::TypeForWasmReturnType(wasm_signature->GetReturn())); 20521cb0ef41Sopenharmony_ci } 20531cb0ef41Sopenharmony_ci } else { 20541cb0ef41Sopenharmony_ci DCHECK_EQ(wasm_signature->return_count(), 0); 20551cb0ef41Sopenharmony_ci SetOutput<T>(node, MachineRepresentation::kTagged); 20561cb0ef41Sopenharmony_ci } 20571cb0ef41Sopenharmony_ci 20581cb0ef41Sopenharmony_ci // The actual lowering of JSWasmCall nodes happens later, in the subsequent 20591cb0ef41Sopenharmony_ci // "wasm-inlining" phase. 20601cb0ef41Sopenharmony_ci } 20611cb0ef41Sopenharmony_ci#endif // V8_ENABLE_WEBASSEMBLY 20621cb0ef41Sopenharmony_ci 20631cb0ef41Sopenharmony_ci // Dispatching routine for visiting the node {node} with the usage {use}. 20641cb0ef41Sopenharmony_ci // Depending on the operator, propagate new usage info to the inputs. 20651cb0ef41Sopenharmony_ci template <Phase T> 20661cb0ef41Sopenharmony_ci void VisitNode(Node* node, Truncation truncation, 20671cb0ef41Sopenharmony_ci SimplifiedLowering* lowering) { 20681cb0ef41Sopenharmony_ci tick_counter_->TickAndMaybeEnterSafepoint(); 20691cb0ef41Sopenharmony_ci 20701cb0ef41Sopenharmony_ci if (lower<T>()) { 20711cb0ef41Sopenharmony_ci // Kill non-effectful operations that have a None-type input and are thus 20721cb0ef41Sopenharmony_ci // dead code. Otherwise we might end up lowering the operation in a way, 20731cb0ef41Sopenharmony_ci // e.g. by replacing it with a constant, that cuts the dependency on a 20741cb0ef41Sopenharmony_ci // deopting operation (the producer of the None type), possibly resulting 20751cb0ef41Sopenharmony_ci // in a nonsense schedule. 20761cb0ef41Sopenharmony_ci if (node->op()->EffectOutputCount() == 0 && 20771cb0ef41Sopenharmony_ci node->op()->ControlOutputCount() == 0 && 20781cb0ef41Sopenharmony_ci node->opcode() != IrOpcode::kDeadValue && 20791cb0ef41Sopenharmony_ci node->opcode() != IrOpcode::kStateValues && 20801cb0ef41Sopenharmony_ci node->opcode() != IrOpcode::kFrameState && 20811cb0ef41Sopenharmony_ci node->opcode() != IrOpcode::kPhi) { 20821cb0ef41Sopenharmony_ci for (int i = 0; i < node->op()->ValueInputCount(); i++) { 20831cb0ef41Sopenharmony_ci Node* input = node->InputAt(i); 20841cb0ef41Sopenharmony_ci if (TypeOf(input).IsNone()) { 20851cb0ef41Sopenharmony_ci node->ReplaceInput(0, input); 20861cb0ef41Sopenharmony_ci node->TrimInputCount(1); 20871cb0ef41Sopenharmony_ci ChangeOp(node, 20881cb0ef41Sopenharmony_ci common()->DeadValue(GetInfo(node)->representation())); 20891cb0ef41Sopenharmony_ci return; 20901cb0ef41Sopenharmony_ci } 20911cb0ef41Sopenharmony_ci } 20921cb0ef41Sopenharmony_ci } else { 20931cb0ef41Sopenharmony_ci InsertUnreachableIfNecessary<T>(node); 20941cb0ef41Sopenharmony_ci } 20951cb0ef41Sopenharmony_ci } 20961cb0ef41Sopenharmony_ci 20971cb0ef41Sopenharmony_ci // Unconditionally eliminate unused pure nodes (only relevant if there's 20981cb0ef41Sopenharmony_ci // a pure operation in between two effectful ones, where the last one 20991cb0ef41Sopenharmony_ci // is unused). 21001cb0ef41Sopenharmony_ci // Note: We must not do this for constants, as they are cached and we 21011cb0ef41Sopenharmony_ci // would thus kill the cached {node} during lowering (i.e. replace all 21021cb0ef41Sopenharmony_ci // uses with Dead), but at that point some node lowering might have 21031cb0ef41Sopenharmony_ci // already taken the constant {node} from the cache (while it was not 21041cb0ef41Sopenharmony_ci // yet killed) and we would afterwards replace that use with Dead as well. 21051cb0ef41Sopenharmony_ci if (node->op()->ValueInputCount() > 0 && 21061cb0ef41Sopenharmony_ci node->op()->HasProperty(Operator::kPure) && truncation.IsUnused()) { 21071cb0ef41Sopenharmony_ci return VisitUnused<T>(node); 21081cb0ef41Sopenharmony_ci } 21091cb0ef41Sopenharmony_ci 21101cb0ef41Sopenharmony_ci switch (node->opcode()) { 21111cb0ef41Sopenharmony_ci //------------------------------------------------------------------ 21121cb0ef41Sopenharmony_ci // Common operators. 21131cb0ef41Sopenharmony_ci //------------------------------------------------------------------ 21141cb0ef41Sopenharmony_ci case IrOpcode::kStart: 21151cb0ef41Sopenharmony_ci // We use Start as a terminator for the frame state chain, so even 21161cb0ef41Sopenharmony_ci // tho Start doesn't really produce a value, we have to say Tagged 21171cb0ef41Sopenharmony_ci // here, otherwise the input conversion will fail. 21181cb0ef41Sopenharmony_ci return VisitLeaf<T>(node, MachineRepresentation::kTagged); 21191cb0ef41Sopenharmony_ci case IrOpcode::kParameter: 21201cb0ef41Sopenharmony_ci return VisitUnop<T>(node, UseInfo::None(), 21211cb0ef41Sopenharmony_ci linkage() 21221cb0ef41Sopenharmony_ci ->GetParameterType(ParameterIndexOf(node->op())) 21231cb0ef41Sopenharmony_ci .representation()); 21241cb0ef41Sopenharmony_ci case IrOpcode::kInt32Constant: 21251cb0ef41Sopenharmony_ci return VisitLeaf<T>(node, MachineRepresentation::kWord32); 21261cb0ef41Sopenharmony_ci case IrOpcode::kInt64Constant: 21271cb0ef41Sopenharmony_ci return VisitLeaf<T>(node, MachineRepresentation::kWord64); 21281cb0ef41Sopenharmony_ci case IrOpcode::kExternalConstant: 21291cb0ef41Sopenharmony_ci return VisitLeaf<T>(node, MachineType::PointerRepresentation()); 21301cb0ef41Sopenharmony_ci case IrOpcode::kNumberConstant: { 21311cb0ef41Sopenharmony_ci double const value = OpParameter<double>(node->op()); 21321cb0ef41Sopenharmony_ci int value_as_int; 21331cb0ef41Sopenharmony_ci if (DoubleToSmiInteger(value, &value_as_int)) { 21341cb0ef41Sopenharmony_ci VisitLeaf<T>(node, MachineRepresentation::kTaggedSigned); 21351cb0ef41Sopenharmony_ci if (lower<T>()) { 21361cb0ef41Sopenharmony_ci intptr_t smi = bit_cast<intptr_t>(Smi::FromInt(value_as_int)); 21371cb0ef41Sopenharmony_ci Node* constant = InsertTypeOverrideForVerifier( 21381cb0ef41Sopenharmony_ci NodeProperties::GetType(node), 21391cb0ef41Sopenharmony_ci lowering->jsgraph()->IntPtrConstant(smi)); 21401cb0ef41Sopenharmony_ci DeferReplacement(node, constant); 21411cb0ef41Sopenharmony_ci } 21421cb0ef41Sopenharmony_ci return; 21431cb0ef41Sopenharmony_ci } 21441cb0ef41Sopenharmony_ci VisitLeaf<T>(node, MachineRepresentation::kTagged); 21451cb0ef41Sopenharmony_ci return; 21461cb0ef41Sopenharmony_ci } 21471cb0ef41Sopenharmony_ci case IrOpcode::kHeapConstant: 21481cb0ef41Sopenharmony_ci case IrOpcode::kDelayedStringConstant: 21491cb0ef41Sopenharmony_ci return VisitLeaf<T>(node, MachineRepresentation::kTaggedPointer); 21501cb0ef41Sopenharmony_ci case IrOpcode::kPointerConstant: { 21511cb0ef41Sopenharmony_ci VisitLeaf<T>(node, MachineType::PointerRepresentation()); 21521cb0ef41Sopenharmony_ci if (lower<T>()) { 21531cb0ef41Sopenharmony_ci intptr_t const value = OpParameter<intptr_t>(node->op()); 21541cb0ef41Sopenharmony_ci DeferReplacement(node, lowering->jsgraph()->IntPtrConstant(value)); 21551cb0ef41Sopenharmony_ci } 21561cb0ef41Sopenharmony_ci return; 21571cb0ef41Sopenharmony_ci } 21581cb0ef41Sopenharmony_ci 21591cb0ef41Sopenharmony_ci case IrOpcode::kBranch: { 21601cb0ef41Sopenharmony_ci DCHECK(TypeOf(node->InputAt(0)).Is(Type::Boolean())); 21611cb0ef41Sopenharmony_ci ProcessInput<T>(node, 0, UseInfo::Bool()); 21621cb0ef41Sopenharmony_ci EnqueueInput<T>(node, NodeProperties::FirstControlIndex(node)); 21631cb0ef41Sopenharmony_ci return; 21641cb0ef41Sopenharmony_ci } 21651cb0ef41Sopenharmony_ci case IrOpcode::kSwitch: 21661cb0ef41Sopenharmony_ci ProcessInput<T>(node, 0, UseInfo::TruncatingWord32()); 21671cb0ef41Sopenharmony_ci EnqueueInput<T>(node, NodeProperties::FirstControlIndex(node)); 21681cb0ef41Sopenharmony_ci return; 21691cb0ef41Sopenharmony_ci case IrOpcode::kSelect: 21701cb0ef41Sopenharmony_ci return VisitSelect<T>(node, truncation, lowering); 21711cb0ef41Sopenharmony_ci case IrOpcode::kPhi: 21721cb0ef41Sopenharmony_ci return VisitPhi<T>(node, truncation, lowering); 21731cb0ef41Sopenharmony_ci case IrOpcode::kCall: 21741cb0ef41Sopenharmony_ci return VisitCall<T>(node, lowering); 21751cb0ef41Sopenharmony_ci 21761cb0ef41Sopenharmony_ci //------------------------------------------------------------------ 21771cb0ef41Sopenharmony_ci // JavaScript operators. 21781cb0ef41Sopenharmony_ci //------------------------------------------------------------------ 21791cb0ef41Sopenharmony_ci case IrOpcode::kJSToNumber: 21801cb0ef41Sopenharmony_ci case IrOpcode::kJSToNumberConvertBigInt: 21811cb0ef41Sopenharmony_ci case IrOpcode::kJSToNumeric: { 21821cb0ef41Sopenharmony_ci DCHECK(NodeProperties::GetType(node).Is(Type::Union( 21831cb0ef41Sopenharmony_ci Type::BigInt(), Type::NumberOrOddball(), graph()->zone()))); 21841cb0ef41Sopenharmony_ci VisitInputs<T>(node); 21851cb0ef41Sopenharmony_ci // TODO(bmeurer): Optimize somewhat based on input type? 21861cb0ef41Sopenharmony_ci if (truncation.IsUsedAsWord32()) { 21871cb0ef41Sopenharmony_ci SetOutput<T>(node, MachineRepresentation::kWord32); 21881cb0ef41Sopenharmony_ci if (lower<T>()) 21891cb0ef41Sopenharmony_ci lowering->DoJSToNumberOrNumericTruncatesToWord32(node, this); 21901cb0ef41Sopenharmony_ci } else if (truncation.TruncatesOddballAndBigIntToNumber()) { 21911cb0ef41Sopenharmony_ci SetOutput<T>(node, MachineRepresentation::kFloat64); 21921cb0ef41Sopenharmony_ci if (lower<T>()) 21931cb0ef41Sopenharmony_ci lowering->DoJSToNumberOrNumericTruncatesToFloat64(node, this); 21941cb0ef41Sopenharmony_ci } else { 21951cb0ef41Sopenharmony_ci SetOutput<T>(node, MachineRepresentation::kTagged); 21961cb0ef41Sopenharmony_ci } 21971cb0ef41Sopenharmony_ci return; 21981cb0ef41Sopenharmony_ci } 21991cb0ef41Sopenharmony_ci 22001cb0ef41Sopenharmony_ci //------------------------------------------------------------------ 22011cb0ef41Sopenharmony_ci // Simplified operators. 22021cb0ef41Sopenharmony_ci //------------------------------------------------------------------ 22031cb0ef41Sopenharmony_ci case IrOpcode::kToBoolean: { 22041cb0ef41Sopenharmony_ci if (truncation.IsUsedAsBool()) { 22051cb0ef41Sopenharmony_ci ProcessInput<T>(node, 0, UseInfo::Bool()); 22061cb0ef41Sopenharmony_ci SetOutput<T>(node, MachineRepresentation::kBit); 22071cb0ef41Sopenharmony_ci if (lower<T>()) DeferReplacement(node, node->InputAt(0)); 22081cb0ef41Sopenharmony_ci } else { 22091cb0ef41Sopenharmony_ci VisitInputs<T>(node); 22101cb0ef41Sopenharmony_ci SetOutput<T>(node, MachineRepresentation::kTaggedPointer); 22111cb0ef41Sopenharmony_ci } 22121cb0ef41Sopenharmony_ci return; 22131cb0ef41Sopenharmony_ci } 22141cb0ef41Sopenharmony_ci case IrOpcode::kBooleanNot: { 22151cb0ef41Sopenharmony_ci if (lower<T>()) { 22161cb0ef41Sopenharmony_ci NodeInfo* input_info = GetInfo(node->InputAt(0)); 22171cb0ef41Sopenharmony_ci if (input_info->representation() == MachineRepresentation::kBit) { 22181cb0ef41Sopenharmony_ci // BooleanNot(x: kRepBit) => Word32Equal(x, #0) 22191cb0ef41Sopenharmony_ci node->AppendInput(jsgraph_->zone(), jsgraph_->Int32Constant(0)); 22201cb0ef41Sopenharmony_ci ChangeOp(node, lowering->machine()->Word32Equal()); 22211cb0ef41Sopenharmony_ci } else if (CanBeTaggedPointer(input_info->representation())) { 22221cb0ef41Sopenharmony_ci // BooleanNot(x: kRepTagged) => WordEqual(x, #false) 22231cb0ef41Sopenharmony_ci node->AppendInput(jsgraph_->zone(), jsgraph_->FalseConstant()); 22241cb0ef41Sopenharmony_ci ChangeOp(node, lowering->machine()->WordEqual()); 22251cb0ef41Sopenharmony_ci } else { 22261cb0ef41Sopenharmony_ci DCHECK(TypeOf(node->InputAt(0)).IsNone()); 22271cb0ef41Sopenharmony_ci DeferReplacement(node, lowering->jsgraph()->Int32Constant(0)); 22281cb0ef41Sopenharmony_ci } 22291cb0ef41Sopenharmony_ci } else { 22301cb0ef41Sopenharmony_ci // No input representation requirement; adapt during lowering. 22311cb0ef41Sopenharmony_ci ProcessInput<T>(node, 0, UseInfo::AnyTruncatingToBool()); 22321cb0ef41Sopenharmony_ci SetOutput<T>(node, MachineRepresentation::kBit); 22331cb0ef41Sopenharmony_ci } 22341cb0ef41Sopenharmony_ci return; 22351cb0ef41Sopenharmony_ci } 22361cb0ef41Sopenharmony_ci case IrOpcode::kNumberEqual: { 22371cb0ef41Sopenharmony_ci Type const lhs_type = TypeOf(node->InputAt(0)); 22381cb0ef41Sopenharmony_ci Type const rhs_type = TypeOf(node->InputAt(1)); 22391cb0ef41Sopenharmony_ci // Regular number comparisons in JavaScript generally identify zeros, 22401cb0ef41Sopenharmony_ci // so we always pass kIdentifyZeros for the inputs, and in addition 22411cb0ef41Sopenharmony_ci // we can truncate -0 to 0 for otherwise Unsigned32 or Signed32 inputs. 22421cb0ef41Sopenharmony_ci // For equality we also handle the case that one side is non-zero, in 22431cb0ef41Sopenharmony_ci // which case we allow to truncate NaN to 0 on the other side. 22441cb0ef41Sopenharmony_ci if ((lhs_type.Is(Type::Unsigned32OrMinusZero()) && 22451cb0ef41Sopenharmony_ci rhs_type.Is(Type::Unsigned32OrMinusZero())) || 22461cb0ef41Sopenharmony_ci (lhs_type.Is(Type::Unsigned32OrMinusZeroOrNaN()) && 22471cb0ef41Sopenharmony_ci rhs_type.Is(Type::Unsigned32OrMinusZeroOrNaN()) && 22481cb0ef41Sopenharmony_ci OneInputCannotBe(node, type_cache_->kZeroish))) { 22491cb0ef41Sopenharmony_ci // => unsigned Int32Cmp 22501cb0ef41Sopenharmony_ci VisitBinop<T>(node, UseInfo::TruncatingWord32(), 22511cb0ef41Sopenharmony_ci MachineRepresentation::kBit); 22521cb0ef41Sopenharmony_ci if (lower<T>()) ChangeOp(node, Uint32Op(node)); 22531cb0ef41Sopenharmony_ci return; 22541cb0ef41Sopenharmony_ci } 22551cb0ef41Sopenharmony_ci if ((lhs_type.Is(Type::Signed32OrMinusZero()) && 22561cb0ef41Sopenharmony_ci rhs_type.Is(Type::Signed32OrMinusZero())) || 22571cb0ef41Sopenharmony_ci (lhs_type.Is(Type::Signed32OrMinusZeroOrNaN()) && 22581cb0ef41Sopenharmony_ci rhs_type.Is(Type::Signed32OrMinusZeroOrNaN()) && 22591cb0ef41Sopenharmony_ci OneInputCannotBe(node, type_cache_->kZeroish))) { 22601cb0ef41Sopenharmony_ci // => signed Int32Cmp 22611cb0ef41Sopenharmony_ci VisitBinop<T>(node, UseInfo::TruncatingWord32(), 22621cb0ef41Sopenharmony_ci MachineRepresentation::kBit); 22631cb0ef41Sopenharmony_ci if (lower<T>()) ChangeOp(node, Int32Op(node)); 22641cb0ef41Sopenharmony_ci return; 22651cb0ef41Sopenharmony_ci } 22661cb0ef41Sopenharmony_ci // => Float64Cmp 22671cb0ef41Sopenharmony_ci VisitBinop<T>(node, UseInfo::TruncatingFloat64(kIdentifyZeros), 22681cb0ef41Sopenharmony_ci MachineRepresentation::kBit); 22691cb0ef41Sopenharmony_ci if (lower<T>()) ChangeOp(node, Float64Op(node)); 22701cb0ef41Sopenharmony_ci return; 22711cb0ef41Sopenharmony_ci } 22721cb0ef41Sopenharmony_ci case IrOpcode::kNumberLessThan: 22731cb0ef41Sopenharmony_ci case IrOpcode::kNumberLessThanOrEqual: { 22741cb0ef41Sopenharmony_ci Type const lhs_type = TypeOf(node->InputAt(0)); 22751cb0ef41Sopenharmony_ci Type const rhs_type = TypeOf(node->InputAt(1)); 22761cb0ef41Sopenharmony_ci // Regular number comparisons in JavaScript generally identify zeros, 22771cb0ef41Sopenharmony_ci // so we always pass kIdentifyZeros for the inputs, and in addition 22781cb0ef41Sopenharmony_ci // we can truncate -0 to 0 for otherwise Unsigned32 or Signed32 inputs. 22791cb0ef41Sopenharmony_ci if (lhs_type.Is(Type::Unsigned32OrMinusZero()) && 22801cb0ef41Sopenharmony_ci rhs_type.Is(Type::Unsigned32OrMinusZero())) { 22811cb0ef41Sopenharmony_ci // => unsigned Int32Cmp 22821cb0ef41Sopenharmony_ci VisitBinop<T>(node, UseInfo::TruncatingWord32(), 22831cb0ef41Sopenharmony_ci MachineRepresentation::kBit); 22841cb0ef41Sopenharmony_ci if (lower<T>()) ChangeOp(node, Uint32Op(node)); 22851cb0ef41Sopenharmony_ci } else if (lhs_type.Is(Type::Signed32OrMinusZero()) && 22861cb0ef41Sopenharmony_ci rhs_type.Is(Type::Signed32OrMinusZero())) { 22871cb0ef41Sopenharmony_ci // => signed Int32Cmp 22881cb0ef41Sopenharmony_ci VisitBinop<T>(node, UseInfo::TruncatingWord32(), 22891cb0ef41Sopenharmony_ci MachineRepresentation::kBit); 22901cb0ef41Sopenharmony_ci if (lower<T>()) ChangeOp(node, Int32Op(node)); 22911cb0ef41Sopenharmony_ci } else { 22921cb0ef41Sopenharmony_ci // => Float64Cmp 22931cb0ef41Sopenharmony_ci VisitBinop<T>(node, UseInfo::TruncatingFloat64(kIdentifyZeros), 22941cb0ef41Sopenharmony_ci MachineRepresentation::kBit); 22951cb0ef41Sopenharmony_ci if (lower<T>()) ChangeOp(node, Float64Op(node)); 22961cb0ef41Sopenharmony_ci } 22971cb0ef41Sopenharmony_ci return; 22981cb0ef41Sopenharmony_ci } 22991cb0ef41Sopenharmony_ci 23001cb0ef41Sopenharmony_ci case IrOpcode::kSpeculativeSafeIntegerAdd: 23011cb0ef41Sopenharmony_ci case IrOpcode::kSpeculativeSafeIntegerSubtract: 23021cb0ef41Sopenharmony_ci return VisitSpeculativeIntegerAdditiveOp<T>(node, truncation, lowering); 23031cb0ef41Sopenharmony_ci 23041cb0ef41Sopenharmony_ci case IrOpcode::kSpeculativeNumberAdd: 23051cb0ef41Sopenharmony_ci case IrOpcode::kSpeculativeNumberSubtract: 23061cb0ef41Sopenharmony_ci return VisitSpeculativeAdditiveOp<T>(node, truncation, lowering); 23071cb0ef41Sopenharmony_ci 23081cb0ef41Sopenharmony_ci case IrOpcode::kSpeculativeNumberLessThan: 23091cb0ef41Sopenharmony_ci case IrOpcode::kSpeculativeNumberLessThanOrEqual: 23101cb0ef41Sopenharmony_ci case IrOpcode::kSpeculativeNumberEqual: { 23111cb0ef41Sopenharmony_ci Type const lhs_type = TypeOf(node->InputAt(0)); 23121cb0ef41Sopenharmony_ci Type const rhs_type = TypeOf(node->InputAt(1)); 23131cb0ef41Sopenharmony_ci // Regular number comparisons in JavaScript generally identify zeros, 23141cb0ef41Sopenharmony_ci // so we always pass kIdentifyZeros for the inputs, and in addition 23151cb0ef41Sopenharmony_ci // we can truncate -0 to 0 for otherwise Unsigned32 or Signed32 inputs. 23161cb0ef41Sopenharmony_ci if (lhs_type.Is(Type::Unsigned32OrMinusZero()) && 23171cb0ef41Sopenharmony_ci rhs_type.Is(Type::Unsigned32OrMinusZero())) { 23181cb0ef41Sopenharmony_ci // => unsigned Int32Cmp 23191cb0ef41Sopenharmony_ci VisitBinop<T>(node, UseInfo::TruncatingWord32(), 23201cb0ef41Sopenharmony_ci MachineRepresentation::kBit); 23211cb0ef41Sopenharmony_ci if (lower<T>()) ChangeToPureOp(node, Uint32Op(node)); 23221cb0ef41Sopenharmony_ci return; 23231cb0ef41Sopenharmony_ci } else if (lhs_type.Is(Type::Signed32OrMinusZero()) && 23241cb0ef41Sopenharmony_ci rhs_type.Is(Type::Signed32OrMinusZero())) { 23251cb0ef41Sopenharmony_ci // => signed Int32Cmp 23261cb0ef41Sopenharmony_ci VisitBinop<T>(node, UseInfo::TruncatingWord32(), 23271cb0ef41Sopenharmony_ci MachineRepresentation::kBit); 23281cb0ef41Sopenharmony_ci if (lower<T>()) ChangeToPureOp(node, Int32Op(node)); 23291cb0ef41Sopenharmony_ci return; 23301cb0ef41Sopenharmony_ci } 23311cb0ef41Sopenharmony_ci // Try to use type feedback. 23321cb0ef41Sopenharmony_ci NumberOperationHint hint = NumberOperationHintOf(node->op()); 23331cb0ef41Sopenharmony_ci switch (hint) { 23341cb0ef41Sopenharmony_ci case NumberOperationHint::kSignedSmall: 23351cb0ef41Sopenharmony_ci if (propagate<T>()) { 23361cb0ef41Sopenharmony_ci VisitBinop<T>( 23371cb0ef41Sopenharmony_ci node, CheckedUseInfoAsWord32FromHint(hint, kIdentifyZeros), 23381cb0ef41Sopenharmony_ci MachineRepresentation::kBit); 23391cb0ef41Sopenharmony_ci } else if (retype<T>()) { 23401cb0ef41Sopenharmony_ci SetOutput<T>(node, MachineRepresentation::kBit, Type::Any()); 23411cb0ef41Sopenharmony_ci } else { 23421cb0ef41Sopenharmony_ci DCHECK(lower<T>()); 23431cb0ef41Sopenharmony_ci Node* lhs = node->InputAt(0); 23441cb0ef41Sopenharmony_ci Node* rhs = node->InputAt(1); 23451cb0ef41Sopenharmony_ci if (IsNodeRepresentationTagged(lhs) && 23461cb0ef41Sopenharmony_ci IsNodeRepresentationTagged(rhs)) { 23471cb0ef41Sopenharmony_ci VisitBinop<T>(node, 23481cb0ef41Sopenharmony_ci UseInfo::CheckedSignedSmallAsTaggedSigned( 23491cb0ef41Sopenharmony_ci FeedbackSource(), kIdentifyZeros), 23501cb0ef41Sopenharmony_ci MachineRepresentation::kBit); 23511cb0ef41Sopenharmony_ci ChangeToPureOp( 23521cb0ef41Sopenharmony_ci node, changer_->TaggedSignedOperatorFor(node->opcode())); 23531cb0ef41Sopenharmony_ci 23541cb0ef41Sopenharmony_ci } else { 23551cb0ef41Sopenharmony_ci VisitBinop<T>( 23561cb0ef41Sopenharmony_ci node, CheckedUseInfoAsWord32FromHint(hint, kIdentifyZeros), 23571cb0ef41Sopenharmony_ci MachineRepresentation::kBit); 23581cb0ef41Sopenharmony_ci ChangeToPureOp(node, Int32Op(node)); 23591cb0ef41Sopenharmony_ci } 23601cb0ef41Sopenharmony_ci } 23611cb0ef41Sopenharmony_ci return; 23621cb0ef41Sopenharmony_ci case NumberOperationHint::kSignedSmallInputs: 23631cb0ef41Sopenharmony_ci // This doesn't make sense for compare operations. 23641cb0ef41Sopenharmony_ci UNREACHABLE(); 23651cb0ef41Sopenharmony_ci case NumberOperationHint::kNumberOrOddball: 23661cb0ef41Sopenharmony_ci // Abstract and strict equality don't perform ToNumber conversions 23671cb0ef41Sopenharmony_ci // on Oddballs, so make sure we don't accidentially sneak in a 23681cb0ef41Sopenharmony_ci // hint with Oddball feedback here. 23691cb0ef41Sopenharmony_ci DCHECK_NE(IrOpcode::kSpeculativeNumberEqual, node->opcode()); 23701cb0ef41Sopenharmony_ci V8_FALLTHROUGH; 23711cb0ef41Sopenharmony_ci case NumberOperationHint::kNumberOrBoolean: 23721cb0ef41Sopenharmony_ci case NumberOperationHint::kNumber: 23731cb0ef41Sopenharmony_ci VisitBinop<T>(node, 23741cb0ef41Sopenharmony_ci CheckedUseInfoAsFloat64FromHint( 23751cb0ef41Sopenharmony_ci hint, FeedbackSource(), kIdentifyZeros), 23761cb0ef41Sopenharmony_ci MachineRepresentation::kBit); 23771cb0ef41Sopenharmony_ci if (lower<T>()) ChangeToPureOp(node, Float64Op(node)); 23781cb0ef41Sopenharmony_ci return; 23791cb0ef41Sopenharmony_ci } 23801cb0ef41Sopenharmony_ci UNREACHABLE(); 23811cb0ef41Sopenharmony_ci return; 23821cb0ef41Sopenharmony_ci } 23831cb0ef41Sopenharmony_ci 23841cb0ef41Sopenharmony_ci case IrOpcode::kNumberAdd: 23851cb0ef41Sopenharmony_ci case IrOpcode::kNumberSubtract: { 23861cb0ef41Sopenharmony_ci if (TypeOf(node->InputAt(0)) 23871cb0ef41Sopenharmony_ci .Is(type_cache_->kAdditiveSafeIntegerOrMinusZero) && 23881cb0ef41Sopenharmony_ci TypeOf(node->InputAt(1)) 23891cb0ef41Sopenharmony_ci .Is(type_cache_->kAdditiveSafeIntegerOrMinusZero) && 23901cb0ef41Sopenharmony_ci (TypeOf(node).Is(Type::Signed32()) || 23911cb0ef41Sopenharmony_ci TypeOf(node).Is(Type::Unsigned32()) || 23921cb0ef41Sopenharmony_ci truncation.IsUsedAsWord32())) { 23931cb0ef41Sopenharmony_ci // => Int32Add/Sub 23941cb0ef41Sopenharmony_ci VisitWord32TruncatingBinop<T>(node); 23951cb0ef41Sopenharmony_ci if (lower<T>()) ChangeToPureOp(node, Int32Op(node)); 23961cb0ef41Sopenharmony_ci } else if (jsgraph_->machine()->Is64() && 23971cb0ef41Sopenharmony_ci BothInputsAre(node, type_cache_->kSafeInteger) && 23981cb0ef41Sopenharmony_ci GetUpperBound(node).Is(type_cache_->kSafeInteger)) { 23991cb0ef41Sopenharmony_ci // => Int64Add/Sub 24001cb0ef41Sopenharmony_ci VisitInt64Binop<T>(node); 24011cb0ef41Sopenharmony_ci if (lower<T>()) ChangeToPureOp(node, Int64Op(node)); 24021cb0ef41Sopenharmony_ci } else { 24031cb0ef41Sopenharmony_ci // => Float64Add/Sub 24041cb0ef41Sopenharmony_ci VisitFloat64Binop<T>(node); 24051cb0ef41Sopenharmony_ci if (lower<T>()) ChangeToPureOp(node, Float64Op(node)); 24061cb0ef41Sopenharmony_ci } 24071cb0ef41Sopenharmony_ci return; 24081cb0ef41Sopenharmony_ci } 24091cb0ef41Sopenharmony_ci case IrOpcode::kSpeculativeNumberMultiply: { 24101cb0ef41Sopenharmony_ci if (BothInputsAre(node, Type::Integral32()) && 24111cb0ef41Sopenharmony_ci (NodeProperties::GetType(node).Is(Type::Signed32()) || 24121cb0ef41Sopenharmony_ci NodeProperties::GetType(node).Is(Type::Unsigned32()) || 24131cb0ef41Sopenharmony_ci (truncation.IsUsedAsWord32() && 24141cb0ef41Sopenharmony_ci NodeProperties::GetType(node).Is( 24151cb0ef41Sopenharmony_ci type_cache_->kSafeIntegerOrMinusZero)))) { 24161cb0ef41Sopenharmony_ci // Multiply reduces to Int32Mul if the inputs are integers, and 24171cb0ef41Sopenharmony_ci // (a) the output is either known to be Signed32, or 24181cb0ef41Sopenharmony_ci // (b) the output is known to be Unsigned32, or 24191cb0ef41Sopenharmony_ci // (c) the uses are truncating and the result is in the safe 24201cb0ef41Sopenharmony_ci // integer range. 24211cb0ef41Sopenharmony_ci VisitWord32TruncatingBinop<T>(node); 24221cb0ef41Sopenharmony_ci if (lower<T>()) ChangeToPureOp(node, Int32Op(node)); 24231cb0ef41Sopenharmony_ci return; 24241cb0ef41Sopenharmony_ci } 24251cb0ef41Sopenharmony_ci // Try to use type feedback. 24261cb0ef41Sopenharmony_ci NumberOperationHint hint = NumberOperationHintOf(node->op()); 24271cb0ef41Sopenharmony_ci Type input0_type = TypeOf(node->InputAt(0)); 24281cb0ef41Sopenharmony_ci Type input1_type = TypeOf(node->InputAt(1)); 24291cb0ef41Sopenharmony_ci 24301cb0ef41Sopenharmony_ci // Handle the case when no int32 checks on inputs are necessary 24311cb0ef41Sopenharmony_ci // (but an overflow check is needed on the output). 24321cb0ef41Sopenharmony_ci if (BothInputsAre(node, Type::Signed32())) { 24331cb0ef41Sopenharmony_ci // If both inputs and feedback are int32, use the overflow op. 24341cb0ef41Sopenharmony_ci if (hint == NumberOperationHint::kSignedSmall) { 24351cb0ef41Sopenharmony_ci VisitForCheckedInt32Mul<T>(node, truncation, input0_type, 24361cb0ef41Sopenharmony_ci input1_type, 24371cb0ef41Sopenharmony_ci UseInfo::TruncatingWord32()); 24381cb0ef41Sopenharmony_ci return; 24391cb0ef41Sopenharmony_ci } 24401cb0ef41Sopenharmony_ci } 24411cb0ef41Sopenharmony_ci 24421cb0ef41Sopenharmony_ci if (hint == NumberOperationHint::kSignedSmall) { 24431cb0ef41Sopenharmony_ci VisitForCheckedInt32Mul<T>(node, truncation, input0_type, input1_type, 24441cb0ef41Sopenharmony_ci CheckedUseInfoAsWord32FromHint(hint)); 24451cb0ef41Sopenharmony_ci return; 24461cb0ef41Sopenharmony_ci } 24471cb0ef41Sopenharmony_ci 24481cb0ef41Sopenharmony_ci // Checked float64 x float64 => float64 24491cb0ef41Sopenharmony_ci VisitBinop<T>(node, 24501cb0ef41Sopenharmony_ci UseInfo::CheckedNumberOrOddballAsFloat64( 24511cb0ef41Sopenharmony_ci kDistinguishZeros, FeedbackSource()), 24521cb0ef41Sopenharmony_ci MachineRepresentation::kFloat64, Type::Number()); 24531cb0ef41Sopenharmony_ci if (lower<T>()) ChangeToPureOp(node, Float64Op(node)); 24541cb0ef41Sopenharmony_ci return; 24551cb0ef41Sopenharmony_ci } 24561cb0ef41Sopenharmony_ci case IrOpcode::kNumberMultiply: { 24571cb0ef41Sopenharmony_ci if (TypeOf(node->InputAt(0)).Is(Type::Integral32()) && 24581cb0ef41Sopenharmony_ci TypeOf(node->InputAt(1)).Is(Type::Integral32()) && 24591cb0ef41Sopenharmony_ci (TypeOf(node).Is(Type::Signed32()) || 24601cb0ef41Sopenharmony_ci TypeOf(node).Is(Type::Unsigned32()) || 24611cb0ef41Sopenharmony_ci (truncation.IsUsedAsWord32() && 24621cb0ef41Sopenharmony_ci TypeOf(node).Is(type_cache_->kSafeIntegerOrMinusZero)))) { 24631cb0ef41Sopenharmony_ci // Multiply reduces to Int32Mul if the inputs are integers, and 24641cb0ef41Sopenharmony_ci // (a) the output is either known to be Signed32, or 24651cb0ef41Sopenharmony_ci // (b) the output is known to be Unsigned32, or 24661cb0ef41Sopenharmony_ci // (c) the uses are truncating and the result is in the safe 24671cb0ef41Sopenharmony_ci // integer range. 24681cb0ef41Sopenharmony_ci VisitWord32TruncatingBinop<T>(node); 24691cb0ef41Sopenharmony_ci if (lower<T>()) ChangeToPureOp(node, Int32Op(node)); 24701cb0ef41Sopenharmony_ci return; 24711cb0ef41Sopenharmony_ci } 24721cb0ef41Sopenharmony_ci // Number x Number => Float64Mul 24731cb0ef41Sopenharmony_ci VisitFloat64Binop<T>(node); 24741cb0ef41Sopenharmony_ci if (lower<T>()) ChangeToPureOp(node, Float64Op(node)); 24751cb0ef41Sopenharmony_ci return; 24761cb0ef41Sopenharmony_ci } 24771cb0ef41Sopenharmony_ci case IrOpcode::kSpeculativeNumberDivide: { 24781cb0ef41Sopenharmony_ci if (BothInputsAreUnsigned32(node) && truncation.IsUsedAsWord32()) { 24791cb0ef41Sopenharmony_ci // => unsigned Uint32Div 24801cb0ef41Sopenharmony_ci VisitWord32TruncatingBinop<T>(node); 24811cb0ef41Sopenharmony_ci if (lower<T>()) DeferReplacement(node, lowering->Uint32Div(node)); 24821cb0ef41Sopenharmony_ci return; 24831cb0ef41Sopenharmony_ci } 24841cb0ef41Sopenharmony_ci if (BothInputsAreSigned32(node)) { 24851cb0ef41Sopenharmony_ci if (NodeProperties::GetType(node).Is(Type::Signed32())) { 24861cb0ef41Sopenharmony_ci // => signed Int32Div 24871cb0ef41Sopenharmony_ci VisitWord32TruncatingBinop<T>(node); 24881cb0ef41Sopenharmony_ci if (lower<T>()) DeferReplacement(node, lowering->Int32Div(node)); 24891cb0ef41Sopenharmony_ci return; 24901cb0ef41Sopenharmony_ci } 24911cb0ef41Sopenharmony_ci if (truncation.IsUsedAsWord32()) { 24921cb0ef41Sopenharmony_ci // => signed Int32Div 24931cb0ef41Sopenharmony_ci VisitWord32TruncatingBinop<T>(node); 24941cb0ef41Sopenharmony_ci if (lower<T>()) DeferReplacement(node, lowering->Int32Div(node)); 24951cb0ef41Sopenharmony_ci return; 24961cb0ef41Sopenharmony_ci } 24971cb0ef41Sopenharmony_ci } 24981cb0ef41Sopenharmony_ci 24991cb0ef41Sopenharmony_ci // Try to use type feedback. 25001cb0ef41Sopenharmony_ci NumberOperationHint hint = NumberOperationHintOf(node->op()); 25011cb0ef41Sopenharmony_ci 25021cb0ef41Sopenharmony_ci // Handle the case when no uint32 checks on inputs are necessary 25031cb0ef41Sopenharmony_ci // (but an overflow check is needed on the output). 25041cb0ef41Sopenharmony_ci if (BothInputsAreUnsigned32(node)) { 25051cb0ef41Sopenharmony_ci if (hint == NumberOperationHint::kSignedSmall) { 25061cb0ef41Sopenharmony_ci VisitBinop<T>(node, UseInfo::TruncatingWord32(), 25071cb0ef41Sopenharmony_ci MachineRepresentation::kWord32, Type::Unsigned32()); 25081cb0ef41Sopenharmony_ci if (lower<T>()) ChangeToUint32OverflowOp(node); 25091cb0ef41Sopenharmony_ci return; 25101cb0ef41Sopenharmony_ci } 25111cb0ef41Sopenharmony_ci } 25121cb0ef41Sopenharmony_ci 25131cb0ef41Sopenharmony_ci // Handle the case when no int32 checks on inputs are necessary 25141cb0ef41Sopenharmony_ci // (but an overflow check is needed on the output). 25151cb0ef41Sopenharmony_ci if (BothInputsAreSigned32(node)) { 25161cb0ef41Sopenharmony_ci // If both the inputs the feedback are int32, use the overflow op. 25171cb0ef41Sopenharmony_ci if (hint == NumberOperationHint::kSignedSmall) { 25181cb0ef41Sopenharmony_ci VisitBinop<T>(node, UseInfo::TruncatingWord32(), 25191cb0ef41Sopenharmony_ci MachineRepresentation::kWord32, Type::Signed32()); 25201cb0ef41Sopenharmony_ci if (lower<T>()) ChangeToInt32OverflowOp(node); 25211cb0ef41Sopenharmony_ci return; 25221cb0ef41Sopenharmony_ci } 25231cb0ef41Sopenharmony_ci } 25241cb0ef41Sopenharmony_ci 25251cb0ef41Sopenharmony_ci if (hint == NumberOperationHint::kSignedSmall || 25261cb0ef41Sopenharmony_ci hint == NumberOperationHint::kSignedSmallInputs) { 25271cb0ef41Sopenharmony_ci // If the result is truncated, we only need to check the inputs. 25281cb0ef41Sopenharmony_ci if (truncation.IsUsedAsWord32()) { 25291cb0ef41Sopenharmony_ci VisitBinop<T>(node, CheckedUseInfoAsWord32FromHint(hint), 25301cb0ef41Sopenharmony_ci MachineRepresentation::kWord32); 25311cb0ef41Sopenharmony_ci if (lower<T>()) DeferReplacement(node, lowering->Int32Div(node)); 25321cb0ef41Sopenharmony_ci return; 25331cb0ef41Sopenharmony_ci } else if (hint != NumberOperationHint::kSignedSmallInputs) { 25341cb0ef41Sopenharmony_ci VisitBinop<T>(node, CheckedUseInfoAsWord32FromHint(hint), 25351cb0ef41Sopenharmony_ci MachineRepresentation::kWord32, Type::Signed32()); 25361cb0ef41Sopenharmony_ci if (lower<T>()) ChangeToInt32OverflowOp(node); 25371cb0ef41Sopenharmony_ci return; 25381cb0ef41Sopenharmony_ci } 25391cb0ef41Sopenharmony_ci } 25401cb0ef41Sopenharmony_ci 25411cb0ef41Sopenharmony_ci // default case => Float64Div 25421cb0ef41Sopenharmony_ci VisitBinop<T>(node, 25431cb0ef41Sopenharmony_ci UseInfo::CheckedNumberOrOddballAsFloat64( 25441cb0ef41Sopenharmony_ci kDistinguishZeros, FeedbackSource()), 25451cb0ef41Sopenharmony_ci MachineRepresentation::kFloat64, Type::Number()); 25461cb0ef41Sopenharmony_ci if (lower<T>()) ChangeToPureOp(node, Float64Op(node)); 25471cb0ef41Sopenharmony_ci return; 25481cb0ef41Sopenharmony_ci } 25491cb0ef41Sopenharmony_ci case IrOpcode::kNumberDivide: { 25501cb0ef41Sopenharmony_ci if (TypeOf(node->InputAt(0)).Is(Type::Unsigned32()) && 25511cb0ef41Sopenharmony_ci TypeOf(node->InputAt(1)).Is(Type::Unsigned32()) && 25521cb0ef41Sopenharmony_ci (truncation.IsUsedAsWord32() || 25531cb0ef41Sopenharmony_ci TypeOf(node).Is(Type::Unsigned32()))) { 25541cb0ef41Sopenharmony_ci // => unsigned Uint32Div 25551cb0ef41Sopenharmony_ci VisitWord32TruncatingBinop<T>(node); 25561cb0ef41Sopenharmony_ci if (lower<T>()) DeferReplacement(node, lowering->Uint32Div(node)); 25571cb0ef41Sopenharmony_ci return; 25581cb0ef41Sopenharmony_ci } 25591cb0ef41Sopenharmony_ci if (TypeOf(node->InputAt(0)).Is(Type::Signed32()) && 25601cb0ef41Sopenharmony_ci TypeOf(node->InputAt(1)).Is(Type::Signed32()) && 25611cb0ef41Sopenharmony_ci (truncation.IsUsedAsWord32() || 25621cb0ef41Sopenharmony_ci TypeOf(node).Is(Type::Signed32()))) { 25631cb0ef41Sopenharmony_ci // => signed Int32Div 25641cb0ef41Sopenharmony_ci VisitWord32TruncatingBinop<T>(node); 25651cb0ef41Sopenharmony_ci if (lower<T>()) DeferReplacement(node, lowering->Int32Div(node)); 25661cb0ef41Sopenharmony_ci return; 25671cb0ef41Sopenharmony_ci } 25681cb0ef41Sopenharmony_ci // Number x Number => Float64Div 25691cb0ef41Sopenharmony_ci VisitFloat64Binop<T>(node); 25701cb0ef41Sopenharmony_ci if (lower<T>()) ChangeToPureOp(node, Float64Op(node)); 25711cb0ef41Sopenharmony_ci return; 25721cb0ef41Sopenharmony_ci } 25731cb0ef41Sopenharmony_ci case IrOpcode::kSpeculativeNumberModulus: 25741cb0ef41Sopenharmony_ci return VisitSpeculativeNumberModulus<T>(node, truncation, lowering); 25751cb0ef41Sopenharmony_ci case IrOpcode::kNumberModulus: { 25761cb0ef41Sopenharmony_ci Type const lhs_type = TypeOf(node->InputAt(0)); 25771cb0ef41Sopenharmony_ci Type const rhs_type = TypeOf(node->InputAt(1)); 25781cb0ef41Sopenharmony_ci if ((lhs_type.Is(Type::Unsigned32OrMinusZeroOrNaN()) && 25791cb0ef41Sopenharmony_ci rhs_type.Is(Type::Unsigned32OrMinusZeroOrNaN())) && 25801cb0ef41Sopenharmony_ci (truncation.IsUsedAsWord32() || 25811cb0ef41Sopenharmony_ci TypeOf(node).Is(Type::Unsigned32()))) { 25821cb0ef41Sopenharmony_ci // => unsigned Uint32Mod 25831cb0ef41Sopenharmony_ci VisitWord32TruncatingBinop<T>(node); 25841cb0ef41Sopenharmony_ci if (lower<T>()) DeferReplacement(node, lowering->Uint32Mod(node)); 25851cb0ef41Sopenharmony_ci return; 25861cb0ef41Sopenharmony_ci } 25871cb0ef41Sopenharmony_ci if ((lhs_type.Is(Type::Signed32OrMinusZeroOrNaN()) && 25881cb0ef41Sopenharmony_ci rhs_type.Is(Type::Signed32OrMinusZeroOrNaN())) && 25891cb0ef41Sopenharmony_ci (truncation.IsUsedAsWord32() || TypeOf(node).Is(Type::Signed32()) || 25901cb0ef41Sopenharmony_ci (truncation.IdentifiesZeroAndMinusZero() && 25911cb0ef41Sopenharmony_ci TypeOf(node).Is(Type::Signed32OrMinusZero())))) { 25921cb0ef41Sopenharmony_ci // => signed Int32Mod 25931cb0ef41Sopenharmony_ci VisitWord32TruncatingBinop<T>(node); 25941cb0ef41Sopenharmony_ci if (lower<T>()) DeferReplacement(node, lowering->Int32Mod(node)); 25951cb0ef41Sopenharmony_ci return; 25961cb0ef41Sopenharmony_ci } 25971cb0ef41Sopenharmony_ci // => Float64Mod 25981cb0ef41Sopenharmony_ci // For the left hand side we just propagate the identify zeros 25991cb0ef41Sopenharmony_ci // mode of the {truncation}; and for modulus the sign of the 26001cb0ef41Sopenharmony_ci // right hand side doesn't matter anyways, so in particular there's 26011cb0ef41Sopenharmony_ci // no observable difference between a 0 and a -0 then. 26021cb0ef41Sopenharmony_ci UseInfo const lhs_use = 26031cb0ef41Sopenharmony_ci UseInfo::TruncatingFloat64(truncation.identify_zeros()); 26041cb0ef41Sopenharmony_ci UseInfo const rhs_use = UseInfo::TruncatingFloat64(kIdentifyZeros); 26051cb0ef41Sopenharmony_ci VisitBinop<T>(node, lhs_use, rhs_use, MachineRepresentation::kFloat64); 26061cb0ef41Sopenharmony_ci if (lower<T>()) ChangeToPureOp(node, Float64Op(node)); 26071cb0ef41Sopenharmony_ci return; 26081cb0ef41Sopenharmony_ci } 26091cb0ef41Sopenharmony_ci case IrOpcode::kNumberBitwiseOr: 26101cb0ef41Sopenharmony_ci case IrOpcode::kNumberBitwiseXor: 26111cb0ef41Sopenharmony_ci case IrOpcode::kNumberBitwiseAnd: { 26121cb0ef41Sopenharmony_ci VisitWord32TruncatingBinop<T>(node); 26131cb0ef41Sopenharmony_ci if (lower<T>()) ChangeOp(node, Int32Op(node)); 26141cb0ef41Sopenharmony_ci return; 26151cb0ef41Sopenharmony_ci } 26161cb0ef41Sopenharmony_ci case IrOpcode::kSpeculativeNumberBitwiseOr: 26171cb0ef41Sopenharmony_ci case IrOpcode::kSpeculativeNumberBitwiseXor: 26181cb0ef41Sopenharmony_ci case IrOpcode::kSpeculativeNumberBitwiseAnd: 26191cb0ef41Sopenharmony_ci VisitSpeculativeInt32Binop<T>(node); 26201cb0ef41Sopenharmony_ci if (lower<T>()) { 26211cb0ef41Sopenharmony_ci ChangeToPureOp(node, Int32Op(node)); 26221cb0ef41Sopenharmony_ci } 26231cb0ef41Sopenharmony_ci return; 26241cb0ef41Sopenharmony_ci case IrOpcode::kNumberShiftLeft: { 26251cb0ef41Sopenharmony_ci Type rhs_type = GetUpperBound(node->InputAt(1)); 26261cb0ef41Sopenharmony_ci VisitBinop<T>(node, UseInfo::TruncatingWord32(), 26271cb0ef41Sopenharmony_ci UseInfo::TruncatingWord32(), 26281cb0ef41Sopenharmony_ci MachineRepresentation::kWord32); 26291cb0ef41Sopenharmony_ci if (lower<T>()) { 26301cb0ef41Sopenharmony_ci MaskShiftOperand(node, rhs_type); 26311cb0ef41Sopenharmony_ci ChangeToPureOp(node, lowering->machine()->Word32Shl()); 26321cb0ef41Sopenharmony_ci } 26331cb0ef41Sopenharmony_ci return; 26341cb0ef41Sopenharmony_ci } 26351cb0ef41Sopenharmony_ci case IrOpcode::kSpeculativeNumberShiftLeft: { 26361cb0ef41Sopenharmony_ci if (BothInputsAre(node, Type::NumberOrOddball())) { 26371cb0ef41Sopenharmony_ci Type rhs_type = GetUpperBound(node->InputAt(1)); 26381cb0ef41Sopenharmony_ci VisitBinop<T>(node, UseInfo::TruncatingWord32(), 26391cb0ef41Sopenharmony_ci UseInfo::TruncatingWord32(), 26401cb0ef41Sopenharmony_ci MachineRepresentation::kWord32); 26411cb0ef41Sopenharmony_ci if (lower<T>()) { 26421cb0ef41Sopenharmony_ci MaskShiftOperand(node, rhs_type); 26431cb0ef41Sopenharmony_ci ChangeToPureOp(node, lowering->machine()->Word32Shl()); 26441cb0ef41Sopenharmony_ci } 26451cb0ef41Sopenharmony_ci return; 26461cb0ef41Sopenharmony_ci } 26471cb0ef41Sopenharmony_ci NumberOperationHint hint = NumberOperationHintOf(node->op()); 26481cb0ef41Sopenharmony_ci Type rhs_type = GetUpperBound(node->InputAt(1)); 26491cb0ef41Sopenharmony_ci VisitBinop<T>(node, 26501cb0ef41Sopenharmony_ci CheckedUseInfoAsWord32FromHint(hint, kIdentifyZeros), 26511cb0ef41Sopenharmony_ci MachineRepresentation::kWord32, Type::Signed32()); 26521cb0ef41Sopenharmony_ci if (lower<T>()) { 26531cb0ef41Sopenharmony_ci MaskShiftOperand(node, rhs_type); 26541cb0ef41Sopenharmony_ci ChangeToPureOp(node, lowering->machine()->Word32Shl()); 26551cb0ef41Sopenharmony_ci } 26561cb0ef41Sopenharmony_ci return; 26571cb0ef41Sopenharmony_ci } 26581cb0ef41Sopenharmony_ci case IrOpcode::kNumberShiftRight: { 26591cb0ef41Sopenharmony_ci Type rhs_type = GetUpperBound(node->InputAt(1)); 26601cb0ef41Sopenharmony_ci VisitBinop<T>(node, UseInfo::TruncatingWord32(), 26611cb0ef41Sopenharmony_ci UseInfo::TruncatingWord32(), 26621cb0ef41Sopenharmony_ci MachineRepresentation::kWord32); 26631cb0ef41Sopenharmony_ci if (lower<T>()) { 26641cb0ef41Sopenharmony_ci MaskShiftOperand(node, rhs_type); 26651cb0ef41Sopenharmony_ci ChangeToPureOp(node, lowering->machine()->Word32Sar()); 26661cb0ef41Sopenharmony_ci } 26671cb0ef41Sopenharmony_ci return; 26681cb0ef41Sopenharmony_ci } 26691cb0ef41Sopenharmony_ci case IrOpcode::kSpeculativeNumberShiftRight: { 26701cb0ef41Sopenharmony_ci if (BothInputsAre(node, Type::NumberOrOddball())) { 26711cb0ef41Sopenharmony_ci Type rhs_type = GetUpperBound(node->InputAt(1)); 26721cb0ef41Sopenharmony_ci VisitBinop<T>(node, UseInfo::TruncatingWord32(), 26731cb0ef41Sopenharmony_ci UseInfo::TruncatingWord32(), 26741cb0ef41Sopenharmony_ci MachineRepresentation::kWord32); 26751cb0ef41Sopenharmony_ci if (lower<T>()) { 26761cb0ef41Sopenharmony_ci MaskShiftOperand(node, rhs_type); 26771cb0ef41Sopenharmony_ci ChangeToPureOp(node, lowering->machine()->Word32Sar()); 26781cb0ef41Sopenharmony_ci } 26791cb0ef41Sopenharmony_ci return; 26801cb0ef41Sopenharmony_ci } 26811cb0ef41Sopenharmony_ci NumberOperationHint hint = NumberOperationHintOf(node->op()); 26821cb0ef41Sopenharmony_ci Type rhs_type = GetUpperBound(node->InputAt(1)); 26831cb0ef41Sopenharmony_ci VisitBinop<T>(node, 26841cb0ef41Sopenharmony_ci CheckedUseInfoAsWord32FromHint(hint, kIdentifyZeros), 26851cb0ef41Sopenharmony_ci MachineRepresentation::kWord32, Type::Signed32()); 26861cb0ef41Sopenharmony_ci if (lower<T>()) { 26871cb0ef41Sopenharmony_ci MaskShiftOperand(node, rhs_type); 26881cb0ef41Sopenharmony_ci ChangeToPureOp(node, lowering->machine()->Word32Sar()); 26891cb0ef41Sopenharmony_ci } 26901cb0ef41Sopenharmony_ci return; 26911cb0ef41Sopenharmony_ci } 26921cb0ef41Sopenharmony_ci case IrOpcode::kNumberShiftRightLogical: { 26931cb0ef41Sopenharmony_ci Type rhs_type = GetUpperBound(node->InputAt(1)); 26941cb0ef41Sopenharmony_ci VisitBinop<T>(node, UseInfo::TruncatingWord32(), 26951cb0ef41Sopenharmony_ci UseInfo::TruncatingWord32(), 26961cb0ef41Sopenharmony_ci MachineRepresentation::kWord32); 26971cb0ef41Sopenharmony_ci if (lower<T>()) { 26981cb0ef41Sopenharmony_ci MaskShiftOperand(node, rhs_type); 26991cb0ef41Sopenharmony_ci ChangeToPureOp(node, lowering->machine()->Word32Shr()); 27001cb0ef41Sopenharmony_ci } 27011cb0ef41Sopenharmony_ci return; 27021cb0ef41Sopenharmony_ci } 27031cb0ef41Sopenharmony_ci case IrOpcode::kSpeculativeNumberShiftRightLogical: { 27041cb0ef41Sopenharmony_ci NumberOperationHint hint = NumberOperationHintOf(node->op()); 27051cb0ef41Sopenharmony_ci Type rhs_type = GetUpperBound(node->InputAt(1)); 27061cb0ef41Sopenharmony_ci if (rhs_type.Is(type_cache_->kZeroish) && 27071cb0ef41Sopenharmony_ci hint == NumberOperationHint::kSignedSmall && 27081cb0ef41Sopenharmony_ci !truncation.IsUsedAsWord32()) { 27091cb0ef41Sopenharmony_ci // The SignedSmall or Signed32 feedback means that the results that we 27101cb0ef41Sopenharmony_ci // have seen so far were of type Unsigned31. We speculate that this 27111cb0ef41Sopenharmony_ci // will continue to hold. Moreover, since the RHS is 0, the result 27121cb0ef41Sopenharmony_ci // will just be the (converted) LHS. 27131cb0ef41Sopenharmony_ci VisitBinop<T>(node, 27141cb0ef41Sopenharmony_ci CheckedUseInfoAsWord32FromHint(hint, kIdentifyZeros), 27151cb0ef41Sopenharmony_ci MachineRepresentation::kWord32, Type::Unsigned31()); 27161cb0ef41Sopenharmony_ci if (lower<T>()) { 27171cb0ef41Sopenharmony_ci node->RemoveInput(1); 27181cb0ef41Sopenharmony_ci ChangeOp(node, 27191cb0ef41Sopenharmony_ci simplified()->CheckedUint32ToInt32(FeedbackSource())); 27201cb0ef41Sopenharmony_ci } 27211cb0ef41Sopenharmony_ci return; 27221cb0ef41Sopenharmony_ci } 27231cb0ef41Sopenharmony_ci if (BothInputsAre(node, Type::NumberOrOddball())) { 27241cb0ef41Sopenharmony_ci VisitBinop<T>(node, UseInfo::TruncatingWord32(), 27251cb0ef41Sopenharmony_ci UseInfo::TruncatingWord32(), 27261cb0ef41Sopenharmony_ci MachineRepresentation::kWord32); 27271cb0ef41Sopenharmony_ci if (lower<T>()) { 27281cb0ef41Sopenharmony_ci MaskShiftOperand(node, rhs_type); 27291cb0ef41Sopenharmony_ci ChangeToPureOp(node, lowering->machine()->Word32Shr()); 27301cb0ef41Sopenharmony_ci } 27311cb0ef41Sopenharmony_ci return; 27321cb0ef41Sopenharmony_ci } 27331cb0ef41Sopenharmony_ci VisitBinop<T>(node, 27341cb0ef41Sopenharmony_ci CheckedUseInfoAsWord32FromHint(hint, kIdentifyZeros), 27351cb0ef41Sopenharmony_ci MachineRepresentation::kWord32, Type::Unsigned32()); 27361cb0ef41Sopenharmony_ci if (lower<T>()) { 27371cb0ef41Sopenharmony_ci MaskShiftOperand(node, rhs_type); 27381cb0ef41Sopenharmony_ci ChangeToPureOp(node, lowering->machine()->Word32Shr()); 27391cb0ef41Sopenharmony_ci } 27401cb0ef41Sopenharmony_ci return; 27411cb0ef41Sopenharmony_ci } 27421cb0ef41Sopenharmony_ci case IrOpcode::kNumberAbs: { 27431cb0ef41Sopenharmony_ci // NumberAbs maps both 0 and -0 to 0, so we can generally 27441cb0ef41Sopenharmony_ci // pass the kIdentifyZeros truncation to its input, and 27451cb0ef41Sopenharmony_ci // choose to ignore minus zero in all cases. 27461cb0ef41Sopenharmony_ci Type const input_type = TypeOf(node->InputAt(0)); 27471cb0ef41Sopenharmony_ci if (input_type.Is(Type::Unsigned32OrMinusZero())) { 27481cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::TruncatingWord32(), 27491cb0ef41Sopenharmony_ci MachineRepresentation::kWord32); 27501cb0ef41Sopenharmony_ci if (lower<T>()) DeferReplacement(node, node->InputAt(0)); 27511cb0ef41Sopenharmony_ci } else if (input_type.Is(Type::Signed32OrMinusZero())) { 27521cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::TruncatingWord32(), 27531cb0ef41Sopenharmony_ci MachineRepresentation::kWord32); 27541cb0ef41Sopenharmony_ci if (lower<T>()) DeferReplacement(node, lowering->Int32Abs(node)); 27551cb0ef41Sopenharmony_ci } else if (input_type.Is(type_cache_->kPositiveIntegerOrNaN)) { 27561cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::TruncatingFloat64(kIdentifyZeros), 27571cb0ef41Sopenharmony_ci MachineRepresentation::kFloat64); 27581cb0ef41Sopenharmony_ci if (lower<T>()) DeferReplacement(node, node->InputAt(0)); 27591cb0ef41Sopenharmony_ci } else { 27601cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::TruncatingFloat64(kIdentifyZeros), 27611cb0ef41Sopenharmony_ci MachineRepresentation::kFloat64); 27621cb0ef41Sopenharmony_ci if (lower<T>()) ChangeOp(node, Float64Op(node)); 27631cb0ef41Sopenharmony_ci } 27641cb0ef41Sopenharmony_ci return; 27651cb0ef41Sopenharmony_ci } 27661cb0ef41Sopenharmony_ci case IrOpcode::kNumberClz32: { 27671cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::TruncatingWord32(), 27681cb0ef41Sopenharmony_ci MachineRepresentation::kWord32); 27691cb0ef41Sopenharmony_ci if (lower<T>()) ChangeOp(node, Uint32Op(node)); 27701cb0ef41Sopenharmony_ci return; 27711cb0ef41Sopenharmony_ci } 27721cb0ef41Sopenharmony_ci case IrOpcode::kNumberImul: { 27731cb0ef41Sopenharmony_ci VisitBinop<T>(node, UseInfo::TruncatingWord32(), 27741cb0ef41Sopenharmony_ci UseInfo::TruncatingWord32(), 27751cb0ef41Sopenharmony_ci MachineRepresentation::kWord32); 27761cb0ef41Sopenharmony_ci if (lower<T>()) ChangeOp(node, Uint32Op(node)); 27771cb0ef41Sopenharmony_ci return; 27781cb0ef41Sopenharmony_ci } 27791cb0ef41Sopenharmony_ci case IrOpcode::kNumberFround: { 27801cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::TruncatingFloat64(), 27811cb0ef41Sopenharmony_ci MachineRepresentation::kFloat32); 27821cb0ef41Sopenharmony_ci if (lower<T>()) ChangeOp(node, Float64Op(node)); 27831cb0ef41Sopenharmony_ci return; 27841cb0ef41Sopenharmony_ci } 27851cb0ef41Sopenharmony_ci case IrOpcode::kNumberMax: { 27861cb0ef41Sopenharmony_ci // It is safe to use the feedback types for left and right hand side 27871cb0ef41Sopenharmony_ci // here, since we can only narrow those types and thus we can only 27881cb0ef41Sopenharmony_ci // promise a more specific truncation. 27891cb0ef41Sopenharmony_ci // For NumberMax we generally propagate whether the truncation 27901cb0ef41Sopenharmony_ci // identifies zeros to the inputs, and we choose to ignore minus 27911cb0ef41Sopenharmony_ci // zero in those cases. 27921cb0ef41Sopenharmony_ci Type const lhs_type = TypeOf(node->InputAt(0)); 27931cb0ef41Sopenharmony_ci Type const rhs_type = TypeOf(node->InputAt(1)); 27941cb0ef41Sopenharmony_ci if ((lhs_type.Is(Type::Unsigned32()) && 27951cb0ef41Sopenharmony_ci rhs_type.Is(Type::Unsigned32())) || 27961cb0ef41Sopenharmony_ci (lhs_type.Is(Type::Unsigned32OrMinusZero()) && 27971cb0ef41Sopenharmony_ci rhs_type.Is(Type::Unsigned32OrMinusZero()) && 27981cb0ef41Sopenharmony_ci truncation.IdentifiesZeroAndMinusZero())) { 27991cb0ef41Sopenharmony_ci VisitWord32TruncatingBinop<T>(node); 28001cb0ef41Sopenharmony_ci if (lower<T>()) { 28011cb0ef41Sopenharmony_ci lowering->DoMax(node, lowering->machine()->Uint32LessThan(), 28021cb0ef41Sopenharmony_ci MachineRepresentation::kWord32); 28031cb0ef41Sopenharmony_ci } 28041cb0ef41Sopenharmony_ci } else if ((lhs_type.Is(Type::Signed32()) && 28051cb0ef41Sopenharmony_ci rhs_type.Is(Type::Signed32())) || 28061cb0ef41Sopenharmony_ci (lhs_type.Is(Type::Signed32OrMinusZero()) && 28071cb0ef41Sopenharmony_ci rhs_type.Is(Type::Signed32OrMinusZero()) && 28081cb0ef41Sopenharmony_ci truncation.IdentifiesZeroAndMinusZero())) { 28091cb0ef41Sopenharmony_ci VisitWord32TruncatingBinop<T>(node); 28101cb0ef41Sopenharmony_ci if (lower<T>()) { 28111cb0ef41Sopenharmony_ci lowering->DoMax(node, lowering->machine()->Int32LessThan(), 28121cb0ef41Sopenharmony_ci MachineRepresentation::kWord32); 28131cb0ef41Sopenharmony_ci } 28141cb0ef41Sopenharmony_ci } else if (jsgraph_->machine()->Is64() && 28151cb0ef41Sopenharmony_ci lhs_type.Is(type_cache_->kSafeInteger) && 28161cb0ef41Sopenharmony_ci rhs_type.Is(type_cache_->kSafeInteger)) { 28171cb0ef41Sopenharmony_ci VisitInt64Binop<T>(node); 28181cb0ef41Sopenharmony_ci if (lower<T>()) { 28191cb0ef41Sopenharmony_ci lowering->DoMax(node, lowering->machine()->Int64LessThan(), 28201cb0ef41Sopenharmony_ci MachineRepresentation::kWord64); 28211cb0ef41Sopenharmony_ci } 28221cb0ef41Sopenharmony_ci } else { 28231cb0ef41Sopenharmony_ci VisitBinop<T>(node, 28241cb0ef41Sopenharmony_ci UseInfo::TruncatingFloat64(truncation.identify_zeros()), 28251cb0ef41Sopenharmony_ci MachineRepresentation::kFloat64); 28261cb0ef41Sopenharmony_ci if (lower<T>()) { 28271cb0ef41Sopenharmony_ci // If the right hand side is not NaN, and the left hand side 28281cb0ef41Sopenharmony_ci // is not NaN (or -0 if the difference between the zeros is 28291cb0ef41Sopenharmony_ci // observed), we can do a simple floating point comparison here. 28301cb0ef41Sopenharmony_ci if (lhs_type.Is(truncation.IdentifiesZeroAndMinusZero() 28311cb0ef41Sopenharmony_ci ? Type::OrderedNumber() 28321cb0ef41Sopenharmony_ci : Type::PlainNumber()) && 28331cb0ef41Sopenharmony_ci rhs_type.Is(Type::OrderedNumber())) { 28341cb0ef41Sopenharmony_ci lowering->DoMax(node, lowering->machine()->Float64LessThan(), 28351cb0ef41Sopenharmony_ci MachineRepresentation::kFloat64); 28361cb0ef41Sopenharmony_ci } else { 28371cb0ef41Sopenharmony_ci ChangeOp(node, Float64Op(node)); 28381cb0ef41Sopenharmony_ci } 28391cb0ef41Sopenharmony_ci } 28401cb0ef41Sopenharmony_ci } 28411cb0ef41Sopenharmony_ci return; 28421cb0ef41Sopenharmony_ci } 28431cb0ef41Sopenharmony_ci case IrOpcode::kNumberMin: { 28441cb0ef41Sopenharmony_ci // It is safe to use the feedback types for left and right hand side 28451cb0ef41Sopenharmony_ci // here, since we can only narrow those types and thus we can only 28461cb0ef41Sopenharmony_ci // promise a more specific truncation. 28471cb0ef41Sopenharmony_ci // For NumberMin we generally propagate whether the truncation 28481cb0ef41Sopenharmony_ci // identifies zeros to the inputs, and we choose to ignore minus 28491cb0ef41Sopenharmony_ci // zero in those cases. 28501cb0ef41Sopenharmony_ci Type const lhs_type = TypeOf(node->InputAt(0)); 28511cb0ef41Sopenharmony_ci Type const rhs_type = TypeOf(node->InputAt(1)); 28521cb0ef41Sopenharmony_ci if ((lhs_type.Is(Type::Unsigned32()) && 28531cb0ef41Sopenharmony_ci rhs_type.Is(Type::Unsigned32())) || 28541cb0ef41Sopenharmony_ci (lhs_type.Is(Type::Unsigned32OrMinusZero()) && 28551cb0ef41Sopenharmony_ci rhs_type.Is(Type::Unsigned32OrMinusZero()) && 28561cb0ef41Sopenharmony_ci truncation.IdentifiesZeroAndMinusZero())) { 28571cb0ef41Sopenharmony_ci VisitWord32TruncatingBinop<T>(node); 28581cb0ef41Sopenharmony_ci if (lower<T>()) { 28591cb0ef41Sopenharmony_ci lowering->DoMin(node, lowering->machine()->Uint32LessThan(), 28601cb0ef41Sopenharmony_ci MachineRepresentation::kWord32); 28611cb0ef41Sopenharmony_ci } 28621cb0ef41Sopenharmony_ci } else if ((lhs_type.Is(Type::Signed32()) && 28631cb0ef41Sopenharmony_ci rhs_type.Is(Type::Signed32())) || 28641cb0ef41Sopenharmony_ci (lhs_type.Is(Type::Signed32OrMinusZero()) && 28651cb0ef41Sopenharmony_ci rhs_type.Is(Type::Signed32OrMinusZero()) && 28661cb0ef41Sopenharmony_ci truncation.IdentifiesZeroAndMinusZero())) { 28671cb0ef41Sopenharmony_ci VisitWord32TruncatingBinop<T>(node); 28681cb0ef41Sopenharmony_ci if (lower<T>()) { 28691cb0ef41Sopenharmony_ci lowering->DoMin(node, lowering->machine()->Int32LessThan(), 28701cb0ef41Sopenharmony_ci MachineRepresentation::kWord32); 28711cb0ef41Sopenharmony_ci } 28721cb0ef41Sopenharmony_ci } else if (jsgraph_->machine()->Is64() && 28731cb0ef41Sopenharmony_ci lhs_type.Is(type_cache_->kSafeInteger) && 28741cb0ef41Sopenharmony_ci rhs_type.Is(type_cache_->kSafeInteger)) { 28751cb0ef41Sopenharmony_ci VisitInt64Binop<T>(node); 28761cb0ef41Sopenharmony_ci if (lower<T>()) { 28771cb0ef41Sopenharmony_ci lowering->DoMin(node, lowering->machine()->Int64LessThan(), 28781cb0ef41Sopenharmony_ci MachineRepresentation::kWord64); 28791cb0ef41Sopenharmony_ci } 28801cb0ef41Sopenharmony_ci } else { 28811cb0ef41Sopenharmony_ci VisitBinop<T>(node, 28821cb0ef41Sopenharmony_ci UseInfo::TruncatingFloat64(truncation.identify_zeros()), 28831cb0ef41Sopenharmony_ci MachineRepresentation::kFloat64); 28841cb0ef41Sopenharmony_ci if (lower<T>()) { 28851cb0ef41Sopenharmony_ci // If the left hand side is not NaN, and the right hand side 28861cb0ef41Sopenharmony_ci // is not NaN (or -0 if the difference between the zeros is 28871cb0ef41Sopenharmony_ci // observed), we can do a simple floating point comparison here. 28881cb0ef41Sopenharmony_ci if (lhs_type.Is(Type::OrderedNumber()) && 28891cb0ef41Sopenharmony_ci rhs_type.Is(truncation.IdentifiesZeroAndMinusZero() 28901cb0ef41Sopenharmony_ci ? Type::OrderedNumber() 28911cb0ef41Sopenharmony_ci : Type::PlainNumber())) { 28921cb0ef41Sopenharmony_ci lowering->DoMin(node, 28931cb0ef41Sopenharmony_ci lowering->machine()->Float64LessThanOrEqual(), 28941cb0ef41Sopenharmony_ci MachineRepresentation::kFloat64); 28951cb0ef41Sopenharmony_ci } else { 28961cb0ef41Sopenharmony_ci ChangeOp(node, Float64Op(node)); 28971cb0ef41Sopenharmony_ci } 28981cb0ef41Sopenharmony_ci } 28991cb0ef41Sopenharmony_ci } 29001cb0ef41Sopenharmony_ci return; 29011cb0ef41Sopenharmony_ci } 29021cb0ef41Sopenharmony_ci case IrOpcode::kSpeculativeNumberPow: { 29031cb0ef41Sopenharmony_ci // Checked float64 ** float64 => float64 29041cb0ef41Sopenharmony_ci VisitBinop<T>(node, 29051cb0ef41Sopenharmony_ci UseInfo::CheckedNumberOrOddballAsFloat64( 29061cb0ef41Sopenharmony_ci kDistinguishZeros, FeedbackSource()), 29071cb0ef41Sopenharmony_ci MachineRepresentation::kFloat64, Type::Number()); 29081cb0ef41Sopenharmony_ci if (lower<T>()) ChangeToPureOp(node, Float64Op(node)); 29091cb0ef41Sopenharmony_ci return; 29101cb0ef41Sopenharmony_ci } 29111cb0ef41Sopenharmony_ci case IrOpcode::kNumberAtan2: 29121cb0ef41Sopenharmony_ci case IrOpcode::kNumberPow: { 29131cb0ef41Sopenharmony_ci VisitBinop<T>(node, UseInfo::TruncatingFloat64(), 29141cb0ef41Sopenharmony_ci MachineRepresentation::kFloat64); 29151cb0ef41Sopenharmony_ci if (lower<T>()) ChangeOp(node, Float64Op(node)); 29161cb0ef41Sopenharmony_ci return; 29171cb0ef41Sopenharmony_ci } 29181cb0ef41Sopenharmony_ci case IrOpcode::kNumberCeil: 29191cb0ef41Sopenharmony_ci case IrOpcode::kNumberFloor: 29201cb0ef41Sopenharmony_ci case IrOpcode::kNumberRound: 29211cb0ef41Sopenharmony_ci case IrOpcode::kNumberTrunc: { 29221cb0ef41Sopenharmony_ci // For NumberCeil, NumberFloor, NumberRound and NumberTrunc we propagate 29231cb0ef41Sopenharmony_ci // the zero identification part of the truncation, and we turn them into 29241cb0ef41Sopenharmony_ci // no-ops if we figure out (late) that their input is already an 29251cb0ef41Sopenharmony_ci // integer, NaN or -0. 29261cb0ef41Sopenharmony_ci Type const input_type = TypeOf(node->InputAt(0)); 29271cb0ef41Sopenharmony_ci VisitUnop<T>(node, 29281cb0ef41Sopenharmony_ci UseInfo::TruncatingFloat64(truncation.identify_zeros()), 29291cb0ef41Sopenharmony_ci MachineRepresentation::kFloat64); 29301cb0ef41Sopenharmony_ci if (lower<T>()) { 29311cb0ef41Sopenharmony_ci if (input_type.Is(type_cache_->kIntegerOrMinusZeroOrNaN)) { 29321cb0ef41Sopenharmony_ci DeferReplacement(node, node->InputAt(0)); 29331cb0ef41Sopenharmony_ci } else if (node->opcode() == IrOpcode::kNumberRound) { 29341cb0ef41Sopenharmony_ci DeferReplacement(node, lowering->Float64Round(node)); 29351cb0ef41Sopenharmony_ci } else { 29361cb0ef41Sopenharmony_ci ChangeOp(node, Float64Op(node)); 29371cb0ef41Sopenharmony_ci } 29381cb0ef41Sopenharmony_ci } 29391cb0ef41Sopenharmony_ci return; 29401cb0ef41Sopenharmony_ci } 29411cb0ef41Sopenharmony_ci case IrOpcode::kCheckBigInt: { 29421cb0ef41Sopenharmony_ci if (InputIs(node, Type::BigInt())) { 29431cb0ef41Sopenharmony_ci VisitNoop<T>(node, truncation); 29441cb0ef41Sopenharmony_ci } else { 29451cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::AnyTagged(), 29461cb0ef41Sopenharmony_ci MachineRepresentation::kTaggedPointer); 29471cb0ef41Sopenharmony_ci } 29481cb0ef41Sopenharmony_ci return; 29491cb0ef41Sopenharmony_ci } 29501cb0ef41Sopenharmony_ci case IrOpcode::kSpeculativeBigIntAsIntN: 29511cb0ef41Sopenharmony_ci case IrOpcode::kSpeculativeBigIntAsUintN: { 29521cb0ef41Sopenharmony_ci const bool is_asuintn = 29531cb0ef41Sopenharmony_ci node->opcode() == IrOpcode::kSpeculativeBigIntAsUintN; 29541cb0ef41Sopenharmony_ci const auto p = SpeculativeBigIntAsNParametersOf(node->op()); 29551cb0ef41Sopenharmony_ci DCHECK_LE(0, p.bits()); 29561cb0ef41Sopenharmony_ci DCHECK_LE(p.bits(), 64); 29571cb0ef41Sopenharmony_ci 29581cb0ef41Sopenharmony_ci ProcessInput<T>(node, 0, 29591cb0ef41Sopenharmony_ci UseInfo::CheckedBigIntTruncatingWord64(p.feedback())); 29601cb0ef41Sopenharmony_ci SetOutput<T>( 29611cb0ef41Sopenharmony_ci node, MachineRepresentation::kWord64, 29621cb0ef41Sopenharmony_ci is_asuintn ? Type::UnsignedBigInt64() : Type::SignedBigInt64()); 29631cb0ef41Sopenharmony_ci if (lower<T>()) { 29641cb0ef41Sopenharmony_ci if (p.bits() == 0) { 29651cb0ef41Sopenharmony_ci DeferReplacement( 29661cb0ef41Sopenharmony_ci node, InsertTypeOverrideForVerifier(Type::UnsignedBigInt63(), 29671cb0ef41Sopenharmony_ci jsgraph_->ZeroConstant())); 29681cb0ef41Sopenharmony_ci } else if (p.bits() == 64) { 29691cb0ef41Sopenharmony_ci DeferReplacement(node, node->InputAt(0)); 29701cb0ef41Sopenharmony_ci } else { 29711cb0ef41Sopenharmony_ci if (is_asuintn) { 29721cb0ef41Sopenharmony_ci const uint64_t mask = (1ULL << p.bits()) - 1ULL; 29731cb0ef41Sopenharmony_ci ChangeUnaryToPureBinaryOp(node, lowering->machine()->Word64And(), 29741cb0ef41Sopenharmony_ci 1, jsgraph_->Int64Constant(mask)); 29751cb0ef41Sopenharmony_ci } else { 29761cb0ef41Sopenharmony_ci // We truncate the value to N bits, but to correctly interpret 29771cb0ef41Sopenharmony_ci // negative values, we have to fill the top (64-N) bits with the 29781cb0ef41Sopenharmony_ci // sign. This is done by shifting the value left and then back 29791cb0ef41Sopenharmony_ci // with an arithmetic right shift. E.g. for {value} = 29801cb0ef41Sopenharmony_ci // 0..0'0001'1101 (29n) and N = 3: {shifted} is 1010'0000'0..0 29811cb0ef41Sopenharmony_ci // after left shift by 61 bits, {unshifted} is 1..1'1111'1101 29821cb0ef41Sopenharmony_ci // after arithmetic right shift by 61. This is the 64 bit 29831cb0ef41Sopenharmony_ci // representation of -3 we expect for the signed 3 bit integer 29841cb0ef41Sopenharmony_ci // 101. 29851cb0ef41Sopenharmony_ci const uint64_t shift = 64 - p.bits(); 29861cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 29871cb0ef41Sopenharmony_ci Node* shifted = 29881cb0ef41Sopenharmony_ci graph()->NewNode(lowering->machine()->Word64Shl(), value, 29891cb0ef41Sopenharmony_ci jsgraph_->Uint64Constant(shift)); 29901cb0ef41Sopenharmony_ci Node* unshifted = 29911cb0ef41Sopenharmony_ci graph()->NewNode(lowering->machine()->Word64Sar(), shifted, 29921cb0ef41Sopenharmony_ci jsgraph_->Uint64Constant(shift)); 29931cb0ef41Sopenharmony_ci 29941cb0ef41Sopenharmony_ci ReplaceWithPureNode(node, unshifted); 29951cb0ef41Sopenharmony_ci } 29961cb0ef41Sopenharmony_ci } 29971cb0ef41Sopenharmony_ci } 29981cb0ef41Sopenharmony_ci return; 29991cb0ef41Sopenharmony_ci } 30001cb0ef41Sopenharmony_ci case IrOpcode::kNumberAcos: 30011cb0ef41Sopenharmony_ci case IrOpcode::kNumberAcosh: 30021cb0ef41Sopenharmony_ci case IrOpcode::kNumberAsin: 30031cb0ef41Sopenharmony_ci case IrOpcode::kNumberAsinh: 30041cb0ef41Sopenharmony_ci case IrOpcode::kNumberAtan: 30051cb0ef41Sopenharmony_ci case IrOpcode::kNumberAtanh: 30061cb0ef41Sopenharmony_ci case IrOpcode::kNumberCos: 30071cb0ef41Sopenharmony_ci case IrOpcode::kNumberCosh: 30081cb0ef41Sopenharmony_ci case IrOpcode::kNumberExp: 30091cb0ef41Sopenharmony_ci case IrOpcode::kNumberExpm1: 30101cb0ef41Sopenharmony_ci case IrOpcode::kNumberLog: 30111cb0ef41Sopenharmony_ci case IrOpcode::kNumberLog1p: 30121cb0ef41Sopenharmony_ci case IrOpcode::kNumberLog2: 30131cb0ef41Sopenharmony_ci case IrOpcode::kNumberLog10: 30141cb0ef41Sopenharmony_ci case IrOpcode::kNumberCbrt: 30151cb0ef41Sopenharmony_ci case IrOpcode::kNumberSin: 30161cb0ef41Sopenharmony_ci case IrOpcode::kNumberSinh: 30171cb0ef41Sopenharmony_ci case IrOpcode::kNumberTan: 30181cb0ef41Sopenharmony_ci case IrOpcode::kNumberTanh: { 30191cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::TruncatingFloat64(), 30201cb0ef41Sopenharmony_ci MachineRepresentation::kFloat64); 30211cb0ef41Sopenharmony_ci if (lower<T>()) ChangeOp(node, Float64Op(node)); 30221cb0ef41Sopenharmony_ci return; 30231cb0ef41Sopenharmony_ci } 30241cb0ef41Sopenharmony_ci case IrOpcode::kNumberSign: { 30251cb0ef41Sopenharmony_ci if (InputIs(node, Type::Signed32())) { 30261cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::TruncatingWord32(), 30271cb0ef41Sopenharmony_ci MachineRepresentation::kWord32); 30281cb0ef41Sopenharmony_ci if (lower<T>()) DeferReplacement(node, lowering->Int32Sign(node)); 30291cb0ef41Sopenharmony_ci } else { 30301cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::TruncatingFloat64(), 30311cb0ef41Sopenharmony_ci MachineRepresentation::kFloat64); 30321cb0ef41Sopenharmony_ci if (lower<T>()) DeferReplacement(node, lowering->Float64Sign(node)); 30331cb0ef41Sopenharmony_ci } 30341cb0ef41Sopenharmony_ci return; 30351cb0ef41Sopenharmony_ci } 30361cb0ef41Sopenharmony_ci case IrOpcode::kNumberSilenceNaN: { 30371cb0ef41Sopenharmony_ci Type const input_type = TypeOf(node->InputAt(0)); 30381cb0ef41Sopenharmony_ci if (input_type.Is(Type::OrderedNumber())) { 30391cb0ef41Sopenharmony_ci // No need to silence anything if the input cannot be NaN. 30401cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::TruncatingFloat64(), 30411cb0ef41Sopenharmony_ci MachineRepresentation::kFloat64); 30421cb0ef41Sopenharmony_ci if (lower<T>()) DeferReplacement(node, node->InputAt(0)); 30431cb0ef41Sopenharmony_ci } else { 30441cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::TruncatingFloat64(), 30451cb0ef41Sopenharmony_ci MachineRepresentation::kFloat64); 30461cb0ef41Sopenharmony_ci if (lower<T>()) ChangeOp(node, Float64Op(node)); 30471cb0ef41Sopenharmony_ci } 30481cb0ef41Sopenharmony_ci return; 30491cb0ef41Sopenharmony_ci } 30501cb0ef41Sopenharmony_ci case IrOpcode::kNumberSqrt: { 30511cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::TruncatingFloat64(), 30521cb0ef41Sopenharmony_ci MachineRepresentation::kFloat64); 30531cb0ef41Sopenharmony_ci if (lower<T>()) ChangeOp(node, Float64Op(node)); 30541cb0ef41Sopenharmony_ci return; 30551cb0ef41Sopenharmony_ci } 30561cb0ef41Sopenharmony_ci case IrOpcode::kNumberToBoolean: { 30571cb0ef41Sopenharmony_ci // For NumberToBoolean we don't care whether the input is 0 or 30581cb0ef41Sopenharmony_ci // -0, since both of them are mapped to false anyways, so we 30591cb0ef41Sopenharmony_ci // can generally pass kIdentifyZeros truncation. 30601cb0ef41Sopenharmony_ci Type const input_type = TypeOf(node->InputAt(0)); 30611cb0ef41Sopenharmony_ci if (input_type.Is(Type::Integral32OrMinusZeroOrNaN())) { 30621cb0ef41Sopenharmony_ci // 0, -0 and NaN all map to false, so we can safely truncate 30631cb0ef41Sopenharmony_ci // all of them to zero here. 30641cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::TruncatingWord32(), 30651cb0ef41Sopenharmony_ci MachineRepresentation::kBit); 30661cb0ef41Sopenharmony_ci if (lower<T>()) lowering->DoIntegral32ToBit(node); 30671cb0ef41Sopenharmony_ci } else if (input_type.Is(Type::OrderedNumber())) { 30681cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::TruncatingFloat64(kIdentifyZeros), 30691cb0ef41Sopenharmony_ci MachineRepresentation::kBit); 30701cb0ef41Sopenharmony_ci if (lower<T>()) lowering->DoOrderedNumberToBit(node); 30711cb0ef41Sopenharmony_ci } else { 30721cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::TruncatingFloat64(kIdentifyZeros), 30731cb0ef41Sopenharmony_ci MachineRepresentation::kBit); 30741cb0ef41Sopenharmony_ci if (lower<T>()) lowering->DoNumberToBit(node); 30751cb0ef41Sopenharmony_ci } 30761cb0ef41Sopenharmony_ci return; 30771cb0ef41Sopenharmony_ci } 30781cb0ef41Sopenharmony_ci case IrOpcode::kNumberToInt32: { 30791cb0ef41Sopenharmony_ci // Just change representation if necessary. 30801cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::TruncatingWord32(), 30811cb0ef41Sopenharmony_ci MachineRepresentation::kWord32); 30821cb0ef41Sopenharmony_ci if (lower<T>()) DeferReplacement(node, node->InputAt(0)); 30831cb0ef41Sopenharmony_ci return; 30841cb0ef41Sopenharmony_ci } 30851cb0ef41Sopenharmony_ci case IrOpcode::kNumberToString: { 30861cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::AnyTagged(), 30871cb0ef41Sopenharmony_ci MachineRepresentation::kTaggedPointer); 30881cb0ef41Sopenharmony_ci return; 30891cb0ef41Sopenharmony_ci } 30901cb0ef41Sopenharmony_ci case IrOpcode::kNumberToUint32: { 30911cb0ef41Sopenharmony_ci // Just change representation if necessary. 30921cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::TruncatingWord32(), 30931cb0ef41Sopenharmony_ci MachineRepresentation::kWord32); 30941cb0ef41Sopenharmony_ci if (lower<T>()) DeferReplacement(node, node->InputAt(0)); 30951cb0ef41Sopenharmony_ci return; 30961cb0ef41Sopenharmony_ci } 30971cb0ef41Sopenharmony_ci case IrOpcode::kNumberToUint8Clamped: { 30981cb0ef41Sopenharmony_ci Type const input_type = TypeOf(node->InputAt(0)); 30991cb0ef41Sopenharmony_ci if (input_type.Is(type_cache_->kUint8OrMinusZeroOrNaN)) { 31001cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::TruncatingWord32(), 31011cb0ef41Sopenharmony_ci MachineRepresentation::kWord32); 31021cb0ef41Sopenharmony_ci if (lower<T>()) DeferReplacement(node, node->InputAt(0)); 31031cb0ef41Sopenharmony_ci } else if (input_type.Is(Type::Unsigned32OrMinusZeroOrNaN())) { 31041cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::TruncatingWord32(), 31051cb0ef41Sopenharmony_ci MachineRepresentation::kWord32); 31061cb0ef41Sopenharmony_ci if (lower<T>()) lowering->DoUnsigned32ToUint8Clamped(node); 31071cb0ef41Sopenharmony_ci } else if (input_type.Is(Type::Signed32OrMinusZeroOrNaN())) { 31081cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::TruncatingWord32(), 31091cb0ef41Sopenharmony_ci MachineRepresentation::kWord32); 31101cb0ef41Sopenharmony_ci if (lower<T>()) lowering->DoSigned32ToUint8Clamped(node); 31111cb0ef41Sopenharmony_ci } else if (input_type.Is(type_cache_->kIntegerOrMinusZeroOrNaN)) { 31121cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::TruncatingFloat64(), 31131cb0ef41Sopenharmony_ci MachineRepresentation::kFloat64); 31141cb0ef41Sopenharmony_ci if (lower<T>()) lowering->DoIntegerToUint8Clamped(node); 31151cb0ef41Sopenharmony_ci } else { 31161cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::TruncatingFloat64(), 31171cb0ef41Sopenharmony_ci MachineRepresentation::kFloat64); 31181cb0ef41Sopenharmony_ci if (lower<T>()) lowering->DoNumberToUint8Clamped(node); 31191cb0ef41Sopenharmony_ci } 31201cb0ef41Sopenharmony_ci return; 31211cb0ef41Sopenharmony_ci } 31221cb0ef41Sopenharmony_ci case IrOpcode::kReferenceEqual: { 31231cb0ef41Sopenharmony_ci VisitBinop<T>(node, UseInfo::AnyTagged(), MachineRepresentation::kBit); 31241cb0ef41Sopenharmony_ci if (lower<T>()) { 31251cb0ef41Sopenharmony_ci if (COMPRESS_POINTERS_BOOL) { 31261cb0ef41Sopenharmony_ci ChangeOp(node, lowering->machine()->Word32Equal()); 31271cb0ef41Sopenharmony_ci } else { 31281cb0ef41Sopenharmony_ci ChangeOp(node, lowering->machine()->WordEqual()); 31291cb0ef41Sopenharmony_ci } 31301cb0ef41Sopenharmony_ci } 31311cb0ef41Sopenharmony_ci return; 31321cb0ef41Sopenharmony_ci } 31331cb0ef41Sopenharmony_ci case IrOpcode::kSameValueNumbersOnly: { 31341cb0ef41Sopenharmony_ci VisitBinop<T>(node, UseInfo::AnyTagged(), 31351cb0ef41Sopenharmony_ci MachineRepresentation::kTaggedPointer); 31361cb0ef41Sopenharmony_ci return; 31371cb0ef41Sopenharmony_ci } 31381cb0ef41Sopenharmony_ci case IrOpcode::kSameValue: { 31391cb0ef41Sopenharmony_ci if (truncation.IsUnused()) return VisitUnused<T>(node); 31401cb0ef41Sopenharmony_ci if (BothInputsAre(node, Type::Number())) { 31411cb0ef41Sopenharmony_ci VisitBinop<T>(node, UseInfo::TruncatingFloat64(), 31421cb0ef41Sopenharmony_ci MachineRepresentation::kBit); 31431cb0ef41Sopenharmony_ci if (lower<T>()) { 31441cb0ef41Sopenharmony_ci ChangeOp(node, lowering->simplified()->NumberSameValue()); 31451cb0ef41Sopenharmony_ci } 31461cb0ef41Sopenharmony_ci } else { 31471cb0ef41Sopenharmony_ci VisitBinop<T>(node, UseInfo::AnyTagged(), 31481cb0ef41Sopenharmony_ci MachineRepresentation::kTaggedPointer); 31491cb0ef41Sopenharmony_ci } 31501cb0ef41Sopenharmony_ci return; 31511cb0ef41Sopenharmony_ci } 31521cb0ef41Sopenharmony_ci case IrOpcode::kTypeOf: { 31531cb0ef41Sopenharmony_ci return VisitUnop<T>(node, UseInfo::AnyTagged(), 31541cb0ef41Sopenharmony_ci MachineRepresentation::kTaggedPointer); 31551cb0ef41Sopenharmony_ci } 31561cb0ef41Sopenharmony_ci case IrOpcode::kNewConsString: { 31571cb0ef41Sopenharmony_ci ProcessInput<T>(node, 0, UseInfo::TruncatingWord32()); // length 31581cb0ef41Sopenharmony_ci ProcessInput<T>(node, 1, UseInfo::AnyTagged()); // first 31591cb0ef41Sopenharmony_ci ProcessInput<T>(node, 2, UseInfo::AnyTagged()); // second 31601cb0ef41Sopenharmony_ci SetOutput<T>(node, MachineRepresentation::kTaggedPointer); 31611cb0ef41Sopenharmony_ci return; 31621cb0ef41Sopenharmony_ci } 31631cb0ef41Sopenharmony_ci case IrOpcode::kSpeculativeBigIntAdd: { 31641cb0ef41Sopenharmony_ci // TODO(nicohartmann@, chromium:1073440): There should be special 31651cb0ef41Sopenharmony_ci // handling for trunction.IsUnused() that correctly propagates deadness, 31661cb0ef41Sopenharmony_ci // but preserves type checking which may throw exceptions. Until this 31671cb0ef41Sopenharmony_ci // is fully supported, we lower to int64 operations but keep pushing 31681cb0ef41Sopenharmony_ci // type constraints. 31691cb0ef41Sopenharmony_ci if (truncation.IsUsedAsWord64()) { 31701cb0ef41Sopenharmony_ci VisitBinop<T>( 31711cb0ef41Sopenharmony_ci node, UseInfo::CheckedBigIntTruncatingWord64(FeedbackSource{}), 31721cb0ef41Sopenharmony_ci MachineRepresentation::kWord64); 31731cb0ef41Sopenharmony_ci if (lower<T>()) { 31741cb0ef41Sopenharmony_ci ChangeToPureOp(node, lowering->machine()->Int64Add()); 31751cb0ef41Sopenharmony_ci } 31761cb0ef41Sopenharmony_ci } else { 31771cb0ef41Sopenharmony_ci VisitBinop<T>(node, 31781cb0ef41Sopenharmony_ci UseInfo::CheckedBigIntAsTaggedPointer(FeedbackSource{}), 31791cb0ef41Sopenharmony_ci MachineRepresentation::kTaggedPointer); 31801cb0ef41Sopenharmony_ci if (lower<T>()) { 31811cb0ef41Sopenharmony_ci ChangeOp(node, lowering->simplified()->BigIntAdd()); 31821cb0ef41Sopenharmony_ci } 31831cb0ef41Sopenharmony_ci } 31841cb0ef41Sopenharmony_ci return; 31851cb0ef41Sopenharmony_ci } 31861cb0ef41Sopenharmony_ci case IrOpcode::kSpeculativeBigIntSubtract: { 31871cb0ef41Sopenharmony_ci if (truncation.IsUsedAsWord64()) { 31881cb0ef41Sopenharmony_ci VisitBinop<T>( 31891cb0ef41Sopenharmony_ci node, UseInfo::CheckedBigIntTruncatingWord64(FeedbackSource{}), 31901cb0ef41Sopenharmony_ci MachineRepresentation::kWord64); 31911cb0ef41Sopenharmony_ci if (lower<T>()) { 31921cb0ef41Sopenharmony_ci ChangeToPureOp(node, lowering->machine()->Int64Sub()); 31931cb0ef41Sopenharmony_ci } 31941cb0ef41Sopenharmony_ci } else { 31951cb0ef41Sopenharmony_ci VisitBinop<T>(node, 31961cb0ef41Sopenharmony_ci UseInfo::CheckedBigIntAsTaggedPointer(FeedbackSource{}), 31971cb0ef41Sopenharmony_ci MachineRepresentation::kTaggedPointer); 31981cb0ef41Sopenharmony_ci if (lower<T>()) { 31991cb0ef41Sopenharmony_ci ChangeOp(node, lowering->simplified()->BigIntSubtract()); 32001cb0ef41Sopenharmony_ci } 32011cb0ef41Sopenharmony_ci } 32021cb0ef41Sopenharmony_ci return; 32031cb0ef41Sopenharmony_ci } 32041cb0ef41Sopenharmony_ci case IrOpcode::kSpeculativeBigIntNegate: { 32051cb0ef41Sopenharmony_ci if (truncation.IsUsedAsWord64()) { 32061cb0ef41Sopenharmony_ci VisitUnop<T>(node, 32071cb0ef41Sopenharmony_ci UseInfo::CheckedBigIntTruncatingWord64(FeedbackSource{}), 32081cb0ef41Sopenharmony_ci MachineRepresentation::kWord64); 32091cb0ef41Sopenharmony_ci if (lower<T>()) { 32101cb0ef41Sopenharmony_ci ChangeUnaryToPureBinaryOp(node, lowering->machine()->Int64Sub(), 0, 32111cb0ef41Sopenharmony_ci jsgraph_->Int64Constant(0)); 32121cb0ef41Sopenharmony_ci } 32131cb0ef41Sopenharmony_ci } else { 32141cb0ef41Sopenharmony_ci VisitUnop<T>(node, 32151cb0ef41Sopenharmony_ci UseInfo::CheckedBigIntAsTaggedPointer(FeedbackSource{}), 32161cb0ef41Sopenharmony_ci MachineRepresentation::kTaggedPointer); 32171cb0ef41Sopenharmony_ci if (lower<T>()) { 32181cb0ef41Sopenharmony_ci ChangeToPureOp(node, lowering->simplified()->BigIntNegate()); 32191cb0ef41Sopenharmony_ci } 32201cb0ef41Sopenharmony_ci } 32211cb0ef41Sopenharmony_ci return; 32221cb0ef41Sopenharmony_ci } 32231cb0ef41Sopenharmony_ci case IrOpcode::kStringConcat: { 32241cb0ef41Sopenharmony_ci // TODO(turbofan): We currently depend on having this first length input 32251cb0ef41Sopenharmony_ci // to make sure that the overflow check is properly scheduled before the 32261cb0ef41Sopenharmony_ci // actual string concatenation. We should also use the length to pass it 32271cb0ef41Sopenharmony_ci // to the builtin or decide in optimized code how to construct the 32281cb0ef41Sopenharmony_ci // resulting string (i.e. cons string or sequential string). 32291cb0ef41Sopenharmony_ci ProcessInput<T>(node, 0, UseInfo::TaggedSigned()); // length 32301cb0ef41Sopenharmony_ci ProcessInput<T>(node, 1, UseInfo::AnyTagged()); // first 32311cb0ef41Sopenharmony_ci ProcessInput<T>(node, 2, UseInfo::AnyTagged()); // second 32321cb0ef41Sopenharmony_ci SetOutput<T>(node, MachineRepresentation::kTaggedPointer); 32331cb0ef41Sopenharmony_ci return; 32341cb0ef41Sopenharmony_ci } 32351cb0ef41Sopenharmony_ci case IrOpcode::kStringEqual: 32361cb0ef41Sopenharmony_ci case IrOpcode::kStringLessThan: 32371cb0ef41Sopenharmony_ci case IrOpcode::kStringLessThanOrEqual: { 32381cb0ef41Sopenharmony_ci return VisitBinop<T>(node, UseInfo::AnyTagged(), 32391cb0ef41Sopenharmony_ci MachineRepresentation::kTaggedPointer); 32401cb0ef41Sopenharmony_ci } 32411cb0ef41Sopenharmony_ci case IrOpcode::kStringCharCodeAt: { 32421cb0ef41Sopenharmony_ci return VisitBinop<T>(node, UseInfo::AnyTagged(), UseInfo::Word(), 32431cb0ef41Sopenharmony_ci MachineRepresentation::kWord32); 32441cb0ef41Sopenharmony_ci } 32451cb0ef41Sopenharmony_ci case IrOpcode::kStringCodePointAt: { 32461cb0ef41Sopenharmony_ci return VisitBinop<T>(node, UseInfo::AnyTagged(), UseInfo::Word(), 32471cb0ef41Sopenharmony_ci MachineRepresentation::kWord32); 32481cb0ef41Sopenharmony_ci } 32491cb0ef41Sopenharmony_ci case IrOpcode::kStringFromSingleCharCode: { 32501cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::TruncatingWord32(), 32511cb0ef41Sopenharmony_ci MachineRepresentation::kTaggedPointer); 32521cb0ef41Sopenharmony_ci return; 32531cb0ef41Sopenharmony_ci } 32541cb0ef41Sopenharmony_ci case IrOpcode::kStringFromSingleCodePoint: { 32551cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::TruncatingWord32(), 32561cb0ef41Sopenharmony_ci MachineRepresentation::kTaggedPointer); 32571cb0ef41Sopenharmony_ci return; 32581cb0ef41Sopenharmony_ci } 32591cb0ef41Sopenharmony_ci case IrOpcode::kStringFromCodePointAt: { 32601cb0ef41Sopenharmony_ci return VisitBinop<T>(node, UseInfo::AnyTagged(), UseInfo::Word(), 32611cb0ef41Sopenharmony_ci MachineRepresentation::kTaggedPointer); 32621cb0ef41Sopenharmony_ci } 32631cb0ef41Sopenharmony_ci case IrOpcode::kStringIndexOf: { 32641cb0ef41Sopenharmony_ci ProcessInput<T>(node, 0, UseInfo::AnyTagged()); 32651cb0ef41Sopenharmony_ci ProcessInput<T>(node, 1, UseInfo::AnyTagged()); 32661cb0ef41Sopenharmony_ci ProcessInput<T>(node, 2, UseInfo::TaggedSigned()); 32671cb0ef41Sopenharmony_ci SetOutput<T>(node, MachineRepresentation::kTaggedSigned); 32681cb0ef41Sopenharmony_ci return; 32691cb0ef41Sopenharmony_ci } 32701cb0ef41Sopenharmony_ci case IrOpcode::kStringLength: { 32711cb0ef41Sopenharmony_ci // TODO(bmeurer): The input representation should be TaggedPointer. 32721cb0ef41Sopenharmony_ci // Fix this once we have a dedicated StringConcat/JSStringAdd 32731cb0ef41Sopenharmony_ci // operator, which marks it's output as TaggedPointer properly. 32741cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::AnyTagged(), 32751cb0ef41Sopenharmony_ci MachineRepresentation::kWord32); 32761cb0ef41Sopenharmony_ci return; 32771cb0ef41Sopenharmony_ci } 32781cb0ef41Sopenharmony_ci case IrOpcode::kStringSubstring: { 32791cb0ef41Sopenharmony_ci ProcessInput<T>(node, 0, UseInfo::AnyTagged()); 32801cb0ef41Sopenharmony_ci ProcessInput<T>(node, 1, UseInfo::TruncatingWord32()); 32811cb0ef41Sopenharmony_ci ProcessInput<T>(node, 2, UseInfo::TruncatingWord32()); 32821cb0ef41Sopenharmony_ci ProcessRemainingInputs<T>(node, 3); 32831cb0ef41Sopenharmony_ci SetOutput<T>(node, MachineRepresentation::kTaggedPointer); 32841cb0ef41Sopenharmony_ci return; 32851cb0ef41Sopenharmony_ci } 32861cb0ef41Sopenharmony_ci case IrOpcode::kStringToLowerCaseIntl: 32871cb0ef41Sopenharmony_ci case IrOpcode::kStringToUpperCaseIntl: { 32881cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::AnyTagged(), 32891cb0ef41Sopenharmony_ci MachineRepresentation::kTaggedPointer); 32901cb0ef41Sopenharmony_ci return; 32911cb0ef41Sopenharmony_ci } 32921cb0ef41Sopenharmony_ci case IrOpcode::kCheckBounds: 32931cb0ef41Sopenharmony_ci return VisitCheckBounds<T>(node, lowering); 32941cb0ef41Sopenharmony_ci case IrOpcode::kCheckHeapObject: { 32951cb0ef41Sopenharmony_ci if (InputCannotBe(node, Type::SignedSmall())) { 32961cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::AnyTagged(), 32971cb0ef41Sopenharmony_ci MachineRepresentation::kTaggedPointer); 32981cb0ef41Sopenharmony_ci } else { 32991cb0ef41Sopenharmony_ci VisitUnop<T>( 33001cb0ef41Sopenharmony_ci node, UseInfo::CheckedHeapObjectAsTaggedPointer(FeedbackSource()), 33011cb0ef41Sopenharmony_ci MachineRepresentation::kTaggedPointer); 33021cb0ef41Sopenharmony_ci } 33031cb0ef41Sopenharmony_ci if (lower<T>()) DeferReplacement(node, node->InputAt(0)); 33041cb0ef41Sopenharmony_ci return; 33051cb0ef41Sopenharmony_ci } 33061cb0ef41Sopenharmony_ci case IrOpcode::kCheckIf: { 33071cb0ef41Sopenharmony_ci ProcessInput<T>(node, 0, UseInfo::Bool()); 33081cb0ef41Sopenharmony_ci ProcessRemainingInputs<T>(node, 1); 33091cb0ef41Sopenharmony_ci SetOutput<T>(node, MachineRepresentation::kNone); 33101cb0ef41Sopenharmony_ci return; 33111cb0ef41Sopenharmony_ci } 33121cb0ef41Sopenharmony_ci case IrOpcode::kCheckInternalizedString: { 33131cb0ef41Sopenharmony_ci VisitCheck<T>(node, Type::InternalizedString(), lowering); 33141cb0ef41Sopenharmony_ci return; 33151cb0ef41Sopenharmony_ci } 33161cb0ef41Sopenharmony_ci case IrOpcode::kCheckNumber: { 33171cb0ef41Sopenharmony_ci Type const input_type = TypeOf(node->InputAt(0)); 33181cb0ef41Sopenharmony_ci if (input_type.Is(Type::Number())) { 33191cb0ef41Sopenharmony_ci VisitNoop<T>(node, truncation); 33201cb0ef41Sopenharmony_ci } else { 33211cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::AnyTagged(), 33221cb0ef41Sopenharmony_ci MachineRepresentation::kTagged); 33231cb0ef41Sopenharmony_ci } 33241cb0ef41Sopenharmony_ci return; 33251cb0ef41Sopenharmony_ci } 33261cb0ef41Sopenharmony_ci case IrOpcode::kCheckReceiver: { 33271cb0ef41Sopenharmony_ci VisitCheck<T>(node, Type::Receiver(), lowering); 33281cb0ef41Sopenharmony_ci return; 33291cb0ef41Sopenharmony_ci } 33301cb0ef41Sopenharmony_ci case IrOpcode::kCheckReceiverOrNullOrUndefined: { 33311cb0ef41Sopenharmony_ci VisitCheck<T>(node, Type::ReceiverOrNullOrUndefined(), lowering); 33321cb0ef41Sopenharmony_ci return; 33331cb0ef41Sopenharmony_ci } 33341cb0ef41Sopenharmony_ci case IrOpcode::kCheckSmi: { 33351cb0ef41Sopenharmony_ci const CheckParameters& params = CheckParametersOf(node->op()); 33361cb0ef41Sopenharmony_ci if (SmiValuesAre32Bits() && truncation.IsUsedAsWord32()) { 33371cb0ef41Sopenharmony_ci VisitUnop<T>(node, 33381cb0ef41Sopenharmony_ci UseInfo::CheckedSignedSmallAsWord32(kDistinguishZeros, 33391cb0ef41Sopenharmony_ci params.feedback()), 33401cb0ef41Sopenharmony_ci MachineRepresentation::kWord32); 33411cb0ef41Sopenharmony_ci } else { 33421cb0ef41Sopenharmony_ci VisitUnop<T>( 33431cb0ef41Sopenharmony_ci node, 33441cb0ef41Sopenharmony_ci UseInfo::CheckedSignedSmallAsTaggedSigned(params.feedback()), 33451cb0ef41Sopenharmony_ci MachineRepresentation::kTaggedSigned); 33461cb0ef41Sopenharmony_ci } 33471cb0ef41Sopenharmony_ci if (lower<T>()) DeferReplacement(node, node->InputAt(0)); 33481cb0ef41Sopenharmony_ci return; 33491cb0ef41Sopenharmony_ci } 33501cb0ef41Sopenharmony_ci case IrOpcode::kCheckString: { 33511cb0ef41Sopenharmony_ci const CheckParameters& params = CheckParametersOf(node->op()); 33521cb0ef41Sopenharmony_ci if (InputIs(node, Type::String())) { 33531cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::AnyTagged(), 33541cb0ef41Sopenharmony_ci MachineRepresentation::kTaggedPointer); 33551cb0ef41Sopenharmony_ci if (lower<T>()) DeferReplacement(node, node->InputAt(0)); 33561cb0ef41Sopenharmony_ci } else { 33571cb0ef41Sopenharmony_ci VisitUnop<T>( 33581cb0ef41Sopenharmony_ci node, 33591cb0ef41Sopenharmony_ci UseInfo::CheckedHeapObjectAsTaggedPointer(params.feedback()), 33601cb0ef41Sopenharmony_ci MachineRepresentation::kTaggedPointer); 33611cb0ef41Sopenharmony_ci } 33621cb0ef41Sopenharmony_ci return; 33631cb0ef41Sopenharmony_ci } 33641cb0ef41Sopenharmony_ci case IrOpcode::kCheckSymbol: { 33651cb0ef41Sopenharmony_ci VisitCheck<T>(node, Type::Symbol(), lowering); 33661cb0ef41Sopenharmony_ci return; 33671cb0ef41Sopenharmony_ci } 33681cb0ef41Sopenharmony_ci 33691cb0ef41Sopenharmony_ci case IrOpcode::kAllocate: { 33701cb0ef41Sopenharmony_ci ProcessInput<T>(node, 0, UseInfo::Word()); 33711cb0ef41Sopenharmony_ci ProcessRemainingInputs<T>(node, 1); 33721cb0ef41Sopenharmony_ci SetOutput<T>(node, MachineRepresentation::kTaggedPointer); 33731cb0ef41Sopenharmony_ci return; 33741cb0ef41Sopenharmony_ci } 33751cb0ef41Sopenharmony_ci case IrOpcode::kLoadFramePointer: { 33761cb0ef41Sopenharmony_ci SetOutput<T>(node, MachineType::PointerRepresentation()); 33771cb0ef41Sopenharmony_ci return; 33781cb0ef41Sopenharmony_ci } 33791cb0ef41Sopenharmony_ci case IrOpcode::kLoadMessage: { 33801cb0ef41Sopenharmony_ci if (truncation.IsUnused()) return VisitUnused<T>(node); 33811cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::Word(), MachineRepresentation::kTagged); 33821cb0ef41Sopenharmony_ci return; 33831cb0ef41Sopenharmony_ci } 33841cb0ef41Sopenharmony_ci case IrOpcode::kStoreMessage: { 33851cb0ef41Sopenharmony_ci ProcessInput<T>(node, 0, UseInfo::Word()); 33861cb0ef41Sopenharmony_ci ProcessInput<T>(node, 1, UseInfo::AnyTagged()); 33871cb0ef41Sopenharmony_ci ProcessRemainingInputs<T>(node, 2); 33881cb0ef41Sopenharmony_ci SetOutput<T>(node, MachineRepresentation::kNone); 33891cb0ef41Sopenharmony_ci return; 33901cb0ef41Sopenharmony_ci } 33911cb0ef41Sopenharmony_ci case IrOpcode::kLoadFieldByIndex: { 33921cb0ef41Sopenharmony_ci if (truncation.IsUnused()) return VisitUnused<T>(node); 33931cb0ef41Sopenharmony_ci VisitBinop<T>(node, UseInfo::AnyTagged(), UseInfo::TruncatingWord32(), 33941cb0ef41Sopenharmony_ci MachineRepresentation::kTagged); 33951cb0ef41Sopenharmony_ci return; 33961cb0ef41Sopenharmony_ci } 33971cb0ef41Sopenharmony_ci case IrOpcode::kLoadField: { 33981cb0ef41Sopenharmony_ci if (truncation.IsUnused()) return VisitUnused<T>(node); 33991cb0ef41Sopenharmony_ci FieldAccess access = FieldAccessOf(node->op()); 34001cb0ef41Sopenharmony_ci MachineRepresentation const representation = 34011cb0ef41Sopenharmony_ci access.machine_type.representation(); 34021cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfoForBasePointer(access), representation); 34031cb0ef41Sopenharmony_ci return; 34041cb0ef41Sopenharmony_ci } 34051cb0ef41Sopenharmony_ci case IrOpcode::kStoreField: { 34061cb0ef41Sopenharmony_ci FieldAccess access = FieldAccessOf(node->op()); 34071cb0ef41Sopenharmony_ci Node* value_node = node->InputAt(1); 34081cb0ef41Sopenharmony_ci NodeInfo* input_info = GetInfo(value_node); 34091cb0ef41Sopenharmony_ci MachineRepresentation field_representation = 34101cb0ef41Sopenharmony_ci access.machine_type.representation(); 34111cb0ef41Sopenharmony_ci 34121cb0ef41Sopenharmony_ci // Convert to Smi if possible, such that we can avoid a write barrier. 34131cb0ef41Sopenharmony_ci if (field_representation == MachineRepresentation::kTagged && 34141cb0ef41Sopenharmony_ci TypeOf(value_node).Is(Type::SignedSmall())) { 34151cb0ef41Sopenharmony_ci field_representation = MachineRepresentation::kTaggedSigned; 34161cb0ef41Sopenharmony_ci } 34171cb0ef41Sopenharmony_ci WriteBarrierKind write_barrier_kind = WriteBarrierKindFor( 34181cb0ef41Sopenharmony_ci access.base_is_tagged, field_representation, access.offset, 34191cb0ef41Sopenharmony_ci access.type, input_info->representation(), value_node); 34201cb0ef41Sopenharmony_ci 34211cb0ef41Sopenharmony_ci ProcessInput<T>(node, 0, UseInfoForBasePointer(access)); 34221cb0ef41Sopenharmony_ci ProcessInput<T>( 34231cb0ef41Sopenharmony_ci node, 1, TruncatingUseInfoFromRepresentation(field_representation)); 34241cb0ef41Sopenharmony_ci ProcessRemainingInputs<T>(node, 2); 34251cb0ef41Sopenharmony_ci SetOutput<T>(node, MachineRepresentation::kNone); 34261cb0ef41Sopenharmony_ci if (lower<T>()) { 34271cb0ef41Sopenharmony_ci if (write_barrier_kind < access.write_barrier_kind) { 34281cb0ef41Sopenharmony_ci access.write_barrier_kind = write_barrier_kind; 34291cb0ef41Sopenharmony_ci ChangeOp(node, jsgraph_->simplified()->StoreField(access)); 34301cb0ef41Sopenharmony_ci } 34311cb0ef41Sopenharmony_ci } 34321cb0ef41Sopenharmony_ci return; 34331cb0ef41Sopenharmony_ci } 34341cb0ef41Sopenharmony_ci case IrOpcode::kLoadElement: { 34351cb0ef41Sopenharmony_ci if (truncation.IsUnused()) return VisitUnused<T>(node); 34361cb0ef41Sopenharmony_ci ElementAccess access = ElementAccessOf(node->op()); 34371cb0ef41Sopenharmony_ci VisitBinop<T>(node, UseInfoForBasePointer(access), UseInfo::Word(), 34381cb0ef41Sopenharmony_ci access.machine_type.representation()); 34391cb0ef41Sopenharmony_ci return; 34401cb0ef41Sopenharmony_ci } 34411cb0ef41Sopenharmony_ci case IrOpcode::kLoadStackArgument: { 34421cb0ef41Sopenharmony_ci if (truncation.IsUnused()) return VisitUnused<T>(node); 34431cb0ef41Sopenharmony_ci VisitBinop<T>(node, UseInfo::Word(), MachineRepresentation::kTagged); 34441cb0ef41Sopenharmony_ci return; 34451cb0ef41Sopenharmony_ci } 34461cb0ef41Sopenharmony_ci case IrOpcode::kStoreElement: { 34471cb0ef41Sopenharmony_ci ElementAccess access = ElementAccessOf(node->op()); 34481cb0ef41Sopenharmony_ci Node* value_node = node->InputAt(2); 34491cb0ef41Sopenharmony_ci NodeInfo* input_info = GetInfo(value_node); 34501cb0ef41Sopenharmony_ci MachineRepresentation element_representation = 34511cb0ef41Sopenharmony_ci access.machine_type.representation(); 34521cb0ef41Sopenharmony_ci 34531cb0ef41Sopenharmony_ci // Convert to Smi if possible, such that we can avoid a write barrier. 34541cb0ef41Sopenharmony_ci if (element_representation == MachineRepresentation::kTagged && 34551cb0ef41Sopenharmony_ci TypeOf(value_node).Is(Type::SignedSmall())) { 34561cb0ef41Sopenharmony_ci element_representation = MachineRepresentation::kTaggedSigned; 34571cb0ef41Sopenharmony_ci } 34581cb0ef41Sopenharmony_ci WriteBarrierKind write_barrier_kind = WriteBarrierKindFor( 34591cb0ef41Sopenharmony_ci access.base_is_tagged, element_representation, access.type, 34601cb0ef41Sopenharmony_ci input_info->representation(), value_node); 34611cb0ef41Sopenharmony_ci ProcessInput<T>(node, 0, UseInfoForBasePointer(access)); // base 34621cb0ef41Sopenharmony_ci ProcessInput<T>(node, 1, UseInfo::Word()); // index 34631cb0ef41Sopenharmony_ci ProcessInput<T>(node, 2, 34641cb0ef41Sopenharmony_ci TruncatingUseInfoFromRepresentation( 34651cb0ef41Sopenharmony_ci element_representation)); // value 34661cb0ef41Sopenharmony_ci ProcessRemainingInputs<T>(node, 3); 34671cb0ef41Sopenharmony_ci SetOutput<T>(node, MachineRepresentation::kNone); 34681cb0ef41Sopenharmony_ci if (lower<T>()) { 34691cb0ef41Sopenharmony_ci if (write_barrier_kind < access.write_barrier_kind) { 34701cb0ef41Sopenharmony_ci access.write_barrier_kind = write_barrier_kind; 34711cb0ef41Sopenharmony_ci ChangeOp(node, jsgraph_->simplified()->StoreElement(access)); 34721cb0ef41Sopenharmony_ci } 34731cb0ef41Sopenharmony_ci } 34741cb0ef41Sopenharmony_ci return; 34751cb0ef41Sopenharmony_ci } 34761cb0ef41Sopenharmony_ci case IrOpcode::kNumberIsFloat64Hole: { 34771cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::TruncatingFloat64(), 34781cb0ef41Sopenharmony_ci MachineRepresentation::kBit); 34791cb0ef41Sopenharmony_ci return; 34801cb0ef41Sopenharmony_ci } 34811cb0ef41Sopenharmony_ci case IrOpcode::kTransitionAndStoreElement: { 34821cb0ef41Sopenharmony_ci Type value_type = TypeOf(node->InputAt(2)); 34831cb0ef41Sopenharmony_ci 34841cb0ef41Sopenharmony_ci ProcessInput<T>(node, 0, UseInfo::AnyTagged()); // array 34851cb0ef41Sopenharmony_ci ProcessInput<T>(node, 1, UseInfo::Word()); // index 34861cb0ef41Sopenharmony_ci 34871cb0ef41Sopenharmony_ci if (value_type.Is(Type::SignedSmall())) { 34881cb0ef41Sopenharmony_ci ProcessInput<T>(node, 2, UseInfo::TruncatingWord32()); // value 34891cb0ef41Sopenharmony_ci if (lower<T>()) { 34901cb0ef41Sopenharmony_ci ChangeOp(node, simplified()->StoreSignedSmallElement()); 34911cb0ef41Sopenharmony_ci } 34921cb0ef41Sopenharmony_ci } else if (value_type.Is(Type::Number())) { 34931cb0ef41Sopenharmony_ci ProcessInput<T>(node, 2, UseInfo::TruncatingFloat64()); // value 34941cb0ef41Sopenharmony_ci if (lower<T>()) { 34951cb0ef41Sopenharmony_ci Handle<Map> double_map = DoubleMapParameterOf(node->op()); 34961cb0ef41Sopenharmony_ci ChangeOp(node, 34971cb0ef41Sopenharmony_ci simplified()->TransitionAndStoreNumberElement(double_map)); 34981cb0ef41Sopenharmony_ci } 34991cb0ef41Sopenharmony_ci } else if (value_type.Is(Type::NonNumber())) { 35001cb0ef41Sopenharmony_ci ProcessInput<T>(node, 2, UseInfo::AnyTagged()); // value 35011cb0ef41Sopenharmony_ci if (lower<T>()) { 35021cb0ef41Sopenharmony_ci Handle<Map> fast_map = FastMapParameterOf(node->op()); 35031cb0ef41Sopenharmony_ci ChangeOp(node, simplified()->TransitionAndStoreNonNumberElement( 35041cb0ef41Sopenharmony_ci fast_map, value_type)); 35051cb0ef41Sopenharmony_ci } 35061cb0ef41Sopenharmony_ci } else { 35071cb0ef41Sopenharmony_ci ProcessInput<T>(node, 2, UseInfo::AnyTagged()); // value 35081cb0ef41Sopenharmony_ci } 35091cb0ef41Sopenharmony_ci 35101cb0ef41Sopenharmony_ci ProcessRemainingInputs<T>(node, 3); 35111cb0ef41Sopenharmony_ci SetOutput<T>(node, MachineRepresentation::kNone); 35121cb0ef41Sopenharmony_ci return; 35131cb0ef41Sopenharmony_ci } 35141cb0ef41Sopenharmony_ci case IrOpcode::kLoadTypedElement: { 35151cb0ef41Sopenharmony_ci MachineRepresentation const rep = 35161cb0ef41Sopenharmony_ci MachineRepresentationFromArrayType(ExternalArrayTypeOf(node->op())); 35171cb0ef41Sopenharmony_ci ProcessInput<T>(node, 0, UseInfo::AnyTagged()); // buffer 35181cb0ef41Sopenharmony_ci ProcessInput<T>(node, 1, UseInfo::AnyTagged()); // base pointer 35191cb0ef41Sopenharmony_ci ProcessInput<T>(node, 2, UseInfo::Word()); // external pointer 35201cb0ef41Sopenharmony_ci ProcessInput<T>(node, 3, UseInfo::Word()); // index 35211cb0ef41Sopenharmony_ci ProcessRemainingInputs<T>(node, 4); 35221cb0ef41Sopenharmony_ci SetOutput<T>(node, rep); 35231cb0ef41Sopenharmony_ci return; 35241cb0ef41Sopenharmony_ci } 35251cb0ef41Sopenharmony_ci case IrOpcode::kLoadDataViewElement: { 35261cb0ef41Sopenharmony_ci MachineRepresentation const rep = 35271cb0ef41Sopenharmony_ci MachineRepresentationFromArrayType(ExternalArrayTypeOf(node->op())); 35281cb0ef41Sopenharmony_ci ProcessInput<T>(node, 0, UseInfo::AnyTagged()); // object 35291cb0ef41Sopenharmony_ci ProcessInput<T>(node, 1, UseInfo::Word()); // base 35301cb0ef41Sopenharmony_ci ProcessInput<T>(node, 2, UseInfo::Word()); // index 35311cb0ef41Sopenharmony_ci ProcessInput<T>(node, 3, UseInfo::Bool()); // little-endian 35321cb0ef41Sopenharmony_ci ProcessRemainingInputs<T>(node, 4); 35331cb0ef41Sopenharmony_ci SetOutput<T>(node, rep); 35341cb0ef41Sopenharmony_ci return; 35351cb0ef41Sopenharmony_ci } 35361cb0ef41Sopenharmony_ci case IrOpcode::kStoreTypedElement: { 35371cb0ef41Sopenharmony_ci MachineRepresentation const rep = 35381cb0ef41Sopenharmony_ci MachineRepresentationFromArrayType(ExternalArrayTypeOf(node->op())); 35391cb0ef41Sopenharmony_ci ProcessInput<T>(node, 0, UseInfo::AnyTagged()); // buffer 35401cb0ef41Sopenharmony_ci ProcessInput<T>(node, 1, UseInfo::AnyTagged()); // base pointer 35411cb0ef41Sopenharmony_ci ProcessInput<T>(node, 2, UseInfo::Word()); // external pointer 35421cb0ef41Sopenharmony_ci ProcessInput<T>(node, 3, UseInfo::Word()); // index 35431cb0ef41Sopenharmony_ci ProcessInput<T>(node, 4, 35441cb0ef41Sopenharmony_ci TruncatingUseInfoFromRepresentation(rep)); // value 35451cb0ef41Sopenharmony_ci ProcessRemainingInputs<T>(node, 5); 35461cb0ef41Sopenharmony_ci SetOutput<T>(node, MachineRepresentation::kNone); 35471cb0ef41Sopenharmony_ci return; 35481cb0ef41Sopenharmony_ci } 35491cb0ef41Sopenharmony_ci case IrOpcode::kStoreDataViewElement: { 35501cb0ef41Sopenharmony_ci MachineRepresentation const rep = 35511cb0ef41Sopenharmony_ci MachineRepresentationFromArrayType(ExternalArrayTypeOf(node->op())); 35521cb0ef41Sopenharmony_ci ProcessInput<T>(node, 0, UseInfo::AnyTagged()); // object 35531cb0ef41Sopenharmony_ci ProcessInput<T>(node, 1, UseInfo::Word()); // base 35541cb0ef41Sopenharmony_ci ProcessInput<T>(node, 2, UseInfo::Word()); // index 35551cb0ef41Sopenharmony_ci ProcessInput<T>(node, 3, 35561cb0ef41Sopenharmony_ci TruncatingUseInfoFromRepresentation(rep)); // value 35571cb0ef41Sopenharmony_ci ProcessInput<T>(node, 4, UseInfo::Bool()); // little-endian 35581cb0ef41Sopenharmony_ci ProcessRemainingInputs<T>(node, 5); 35591cb0ef41Sopenharmony_ci SetOutput<T>(node, MachineRepresentation::kNone); 35601cb0ef41Sopenharmony_ci return; 35611cb0ef41Sopenharmony_ci } 35621cb0ef41Sopenharmony_ci case IrOpcode::kConvertReceiver: { 35631cb0ef41Sopenharmony_ci Type input_type = TypeOf(node->InputAt(0)); 35641cb0ef41Sopenharmony_ci VisitBinop<T>(node, UseInfo::AnyTagged(), 35651cb0ef41Sopenharmony_ci MachineRepresentation::kTaggedPointer); 35661cb0ef41Sopenharmony_ci if (lower<T>()) { 35671cb0ef41Sopenharmony_ci // Try to optimize the {node} based on the input type. 35681cb0ef41Sopenharmony_ci if (input_type.Is(Type::Receiver())) { 35691cb0ef41Sopenharmony_ci DeferReplacement(node, node->InputAt(0)); 35701cb0ef41Sopenharmony_ci } else if (input_type.Is(Type::NullOrUndefined())) { 35711cb0ef41Sopenharmony_ci DeferReplacement(node, node->InputAt(1)); 35721cb0ef41Sopenharmony_ci } else if (!input_type.Maybe(Type::NullOrUndefined())) { 35731cb0ef41Sopenharmony_ci ChangeOp(node, lowering->simplified()->ConvertReceiver( 35741cb0ef41Sopenharmony_ci ConvertReceiverMode::kNotNullOrUndefined)); 35751cb0ef41Sopenharmony_ci } 35761cb0ef41Sopenharmony_ci } 35771cb0ef41Sopenharmony_ci return; 35781cb0ef41Sopenharmony_ci } 35791cb0ef41Sopenharmony_ci case IrOpcode::kPlainPrimitiveToNumber: { 35801cb0ef41Sopenharmony_ci if (InputIs(node, Type::Boolean())) { 35811cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::Bool(), MachineRepresentation::kWord32); 35821cb0ef41Sopenharmony_ci if (lower<T>()) { 35831cb0ef41Sopenharmony_ci ChangeToSemanticsHintForVerifier(node, node->op()); 35841cb0ef41Sopenharmony_ci } 35851cb0ef41Sopenharmony_ci } else if (InputIs(node, Type::String())) { 35861cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::AnyTagged(), 35871cb0ef41Sopenharmony_ci MachineRepresentation::kTagged); 35881cb0ef41Sopenharmony_ci if (lower<T>()) { 35891cb0ef41Sopenharmony_ci ChangeOp(node, simplified()->StringToNumber()); 35901cb0ef41Sopenharmony_ci } 35911cb0ef41Sopenharmony_ci } else if (truncation.IsUsedAsWord32()) { 35921cb0ef41Sopenharmony_ci if (InputIs(node, Type::NumberOrOddball())) { 35931cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::TruncatingWord32(), 35941cb0ef41Sopenharmony_ci MachineRepresentation::kWord32); 35951cb0ef41Sopenharmony_ci if (lower<T>()) { 35961cb0ef41Sopenharmony_ci ChangeToSemanticsHintForVerifier(node, node->op()); 35971cb0ef41Sopenharmony_ci } 35981cb0ef41Sopenharmony_ci } else { 35991cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::AnyTagged(), 36001cb0ef41Sopenharmony_ci MachineRepresentation::kWord32); 36011cb0ef41Sopenharmony_ci if (lower<T>()) { 36021cb0ef41Sopenharmony_ci ChangeOp(node, simplified()->PlainPrimitiveToWord32()); 36031cb0ef41Sopenharmony_ci } 36041cb0ef41Sopenharmony_ci } 36051cb0ef41Sopenharmony_ci } else if (truncation.TruncatesOddballAndBigIntToNumber()) { 36061cb0ef41Sopenharmony_ci if (InputIs(node, Type::NumberOrOddball())) { 36071cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::TruncatingFloat64(), 36081cb0ef41Sopenharmony_ci MachineRepresentation::kFloat64); 36091cb0ef41Sopenharmony_ci if (lower<T>()) { 36101cb0ef41Sopenharmony_ci ChangeToSemanticsHintForVerifier(node, node->op()); 36111cb0ef41Sopenharmony_ci } 36121cb0ef41Sopenharmony_ci } else { 36131cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::AnyTagged(), 36141cb0ef41Sopenharmony_ci MachineRepresentation::kFloat64); 36151cb0ef41Sopenharmony_ci if (lower<T>()) { 36161cb0ef41Sopenharmony_ci ChangeOp(node, simplified()->PlainPrimitiveToFloat64()); 36171cb0ef41Sopenharmony_ci } 36181cb0ef41Sopenharmony_ci } 36191cb0ef41Sopenharmony_ci } else { 36201cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::AnyTagged(), 36211cb0ef41Sopenharmony_ci MachineRepresentation::kTagged); 36221cb0ef41Sopenharmony_ci } 36231cb0ef41Sopenharmony_ci return; 36241cb0ef41Sopenharmony_ci } 36251cb0ef41Sopenharmony_ci case IrOpcode::kSpeculativeToNumber: { 36261cb0ef41Sopenharmony_ci NumberOperationParameters const& p = 36271cb0ef41Sopenharmony_ci NumberOperationParametersOf(node->op()); 36281cb0ef41Sopenharmony_ci switch (p.hint()) { 36291cb0ef41Sopenharmony_ci case NumberOperationHint::kSignedSmall: 36301cb0ef41Sopenharmony_ci case NumberOperationHint::kSignedSmallInputs: 36311cb0ef41Sopenharmony_ci VisitUnop<T>(node, 36321cb0ef41Sopenharmony_ci CheckedUseInfoAsWord32FromHint( 36331cb0ef41Sopenharmony_ci p.hint(), kDistinguishZeros, p.feedback()), 36341cb0ef41Sopenharmony_ci MachineRepresentation::kWord32, Type::Signed32()); 36351cb0ef41Sopenharmony_ci break; 36361cb0ef41Sopenharmony_ci case NumberOperationHint::kNumber: 36371cb0ef41Sopenharmony_ci case NumberOperationHint::kNumberOrBoolean: 36381cb0ef41Sopenharmony_ci case NumberOperationHint::kNumberOrOddball: 36391cb0ef41Sopenharmony_ci VisitUnop<T>( 36401cb0ef41Sopenharmony_ci node, CheckedUseInfoAsFloat64FromHint(p.hint(), p.feedback()), 36411cb0ef41Sopenharmony_ci MachineRepresentation::kFloat64); 36421cb0ef41Sopenharmony_ci break; 36431cb0ef41Sopenharmony_ci } 36441cb0ef41Sopenharmony_ci if (lower<T>()) DeferReplacement(node, node->InputAt(0)); 36451cb0ef41Sopenharmony_ci return; 36461cb0ef41Sopenharmony_ci } 36471cb0ef41Sopenharmony_ci case IrOpcode::kObjectIsArrayBufferView: { 36481cb0ef41Sopenharmony_ci // TODO(turbofan): Introduce a Type::ArrayBufferView? 36491cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::AnyTagged(), MachineRepresentation::kBit); 36501cb0ef41Sopenharmony_ci return; 36511cb0ef41Sopenharmony_ci } 36521cb0ef41Sopenharmony_ci case IrOpcode::kObjectIsBigInt: { 36531cb0ef41Sopenharmony_ci VisitObjectIs<T>(node, Type::BigInt(), lowering); 36541cb0ef41Sopenharmony_ci return; 36551cb0ef41Sopenharmony_ci } 36561cb0ef41Sopenharmony_ci case IrOpcode::kObjectIsCallable: { 36571cb0ef41Sopenharmony_ci VisitObjectIs<T>(node, Type::Callable(), lowering); 36581cb0ef41Sopenharmony_ci return; 36591cb0ef41Sopenharmony_ci } 36601cb0ef41Sopenharmony_ci case IrOpcode::kObjectIsConstructor: { 36611cb0ef41Sopenharmony_ci // TODO(turbofan): Introduce a Type::Constructor? 36621cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::AnyTagged(), MachineRepresentation::kBit); 36631cb0ef41Sopenharmony_ci return; 36641cb0ef41Sopenharmony_ci } 36651cb0ef41Sopenharmony_ci case IrOpcode::kObjectIsDetectableCallable: { 36661cb0ef41Sopenharmony_ci VisitObjectIs<T>(node, Type::DetectableCallable(), lowering); 36671cb0ef41Sopenharmony_ci return; 36681cb0ef41Sopenharmony_ci } 36691cb0ef41Sopenharmony_ci case IrOpcode::kObjectIsFiniteNumber: { 36701cb0ef41Sopenharmony_ci Type const input_type = GetUpperBound(node->InputAt(0)); 36711cb0ef41Sopenharmony_ci if (input_type.Is(type_cache_->kSafeInteger)) { 36721cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::None(), MachineRepresentation::kBit); 36731cb0ef41Sopenharmony_ci if (lower<T>()) { 36741cb0ef41Sopenharmony_ci DeferReplacement(node, lowering->jsgraph()->Int32Constant(1)); 36751cb0ef41Sopenharmony_ci } 36761cb0ef41Sopenharmony_ci } else if (!input_type.Maybe(Type::Number())) { 36771cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::Any(), MachineRepresentation::kBit); 36781cb0ef41Sopenharmony_ci if (lower<T>()) { 36791cb0ef41Sopenharmony_ci DeferReplacement(node, lowering->jsgraph()->Int32Constant(0)); 36801cb0ef41Sopenharmony_ci } 36811cb0ef41Sopenharmony_ci } else if (input_type.Is(Type::Number())) { 36821cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::TruncatingFloat64(), 36831cb0ef41Sopenharmony_ci MachineRepresentation::kBit); 36841cb0ef41Sopenharmony_ci if (lower<T>()) { 36851cb0ef41Sopenharmony_ci ChangeOp(node, lowering->simplified()->NumberIsFinite()); 36861cb0ef41Sopenharmony_ci } 36871cb0ef41Sopenharmony_ci } else { 36881cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::AnyTagged(), MachineRepresentation::kBit); 36891cb0ef41Sopenharmony_ci } 36901cb0ef41Sopenharmony_ci return; 36911cb0ef41Sopenharmony_ci } 36921cb0ef41Sopenharmony_ci case IrOpcode::kNumberIsFinite: { 36931cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::TruncatingFloat64(), 36941cb0ef41Sopenharmony_ci MachineRepresentation::kBit); 36951cb0ef41Sopenharmony_ci return; 36961cb0ef41Sopenharmony_ci } 36971cb0ef41Sopenharmony_ci case IrOpcode::kObjectIsSafeInteger: { 36981cb0ef41Sopenharmony_ci Type const input_type = GetUpperBound(node->InputAt(0)); 36991cb0ef41Sopenharmony_ci if (input_type.Is(type_cache_->kSafeInteger)) { 37001cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::None(), MachineRepresentation::kBit); 37011cb0ef41Sopenharmony_ci if (lower<T>()) { 37021cb0ef41Sopenharmony_ci DeferReplacement(node, lowering->jsgraph()->Int32Constant(1)); 37031cb0ef41Sopenharmony_ci } 37041cb0ef41Sopenharmony_ci } else if (!input_type.Maybe(Type::Number())) { 37051cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::Any(), MachineRepresentation::kBit); 37061cb0ef41Sopenharmony_ci if (lower<T>()) { 37071cb0ef41Sopenharmony_ci DeferReplacement(node, lowering->jsgraph()->Int32Constant(0)); 37081cb0ef41Sopenharmony_ci } 37091cb0ef41Sopenharmony_ci } else if (input_type.Is(Type::Number())) { 37101cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::TruncatingFloat64(), 37111cb0ef41Sopenharmony_ci MachineRepresentation::kBit); 37121cb0ef41Sopenharmony_ci if (lower<T>()) { 37131cb0ef41Sopenharmony_ci ChangeOp(node, lowering->simplified()->NumberIsSafeInteger()); 37141cb0ef41Sopenharmony_ci } 37151cb0ef41Sopenharmony_ci } else { 37161cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::AnyTagged(), MachineRepresentation::kBit); 37171cb0ef41Sopenharmony_ci } 37181cb0ef41Sopenharmony_ci return; 37191cb0ef41Sopenharmony_ci } 37201cb0ef41Sopenharmony_ci case IrOpcode::kNumberIsSafeInteger: { 37211cb0ef41Sopenharmony_ci UNREACHABLE(); 37221cb0ef41Sopenharmony_ci } 37231cb0ef41Sopenharmony_ci case IrOpcode::kObjectIsInteger: { 37241cb0ef41Sopenharmony_ci Type const input_type = GetUpperBound(node->InputAt(0)); 37251cb0ef41Sopenharmony_ci if (input_type.Is(type_cache_->kSafeInteger)) { 37261cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::None(), MachineRepresentation::kBit); 37271cb0ef41Sopenharmony_ci if (lower<T>()) { 37281cb0ef41Sopenharmony_ci DeferReplacement(node, lowering->jsgraph()->Int32Constant(1)); 37291cb0ef41Sopenharmony_ci } 37301cb0ef41Sopenharmony_ci } else if (!input_type.Maybe(Type::Number())) { 37311cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::Any(), MachineRepresentation::kBit); 37321cb0ef41Sopenharmony_ci if (lower<T>()) { 37331cb0ef41Sopenharmony_ci DeferReplacement(node, lowering->jsgraph()->Int32Constant(0)); 37341cb0ef41Sopenharmony_ci } 37351cb0ef41Sopenharmony_ci } else if (input_type.Is(Type::Number())) { 37361cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::TruncatingFloat64(), 37371cb0ef41Sopenharmony_ci MachineRepresentation::kBit); 37381cb0ef41Sopenharmony_ci if (lower<T>()) { 37391cb0ef41Sopenharmony_ci ChangeOp(node, lowering->simplified()->NumberIsInteger()); 37401cb0ef41Sopenharmony_ci } 37411cb0ef41Sopenharmony_ci } else { 37421cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::AnyTagged(), MachineRepresentation::kBit); 37431cb0ef41Sopenharmony_ci } 37441cb0ef41Sopenharmony_ci return; 37451cb0ef41Sopenharmony_ci } 37461cb0ef41Sopenharmony_ci case IrOpcode::kNumberIsInteger: { 37471cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::TruncatingFloat64(), 37481cb0ef41Sopenharmony_ci MachineRepresentation::kBit); 37491cb0ef41Sopenharmony_ci return; 37501cb0ef41Sopenharmony_ci } 37511cb0ef41Sopenharmony_ci case IrOpcode::kObjectIsMinusZero: { 37521cb0ef41Sopenharmony_ci Type const input_type = GetUpperBound(node->InputAt(0)); 37531cb0ef41Sopenharmony_ci if (input_type.Is(Type::MinusZero())) { 37541cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::None(), MachineRepresentation::kBit); 37551cb0ef41Sopenharmony_ci if (lower<T>()) { 37561cb0ef41Sopenharmony_ci DeferReplacement(node, lowering->jsgraph()->Int32Constant(1)); 37571cb0ef41Sopenharmony_ci } 37581cb0ef41Sopenharmony_ci } else if (!input_type.Maybe(Type::MinusZero())) { 37591cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::Any(), MachineRepresentation::kBit); 37601cb0ef41Sopenharmony_ci if (lower<T>()) { 37611cb0ef41Sopenharmony_ci DeferReplacement(node, lowering->jsgraph()->Int32Constant(0)); 37621cb0ef41Sopenharmony_ci } 37631cb0ef41Sopenharmony_ci } else if (input_type.Is(Type::Number())) { 37641cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::TruncatingFloat64(), 37651cb0ef41Sopenharmony_ci MachineRepresentation::kBit); 37661cb0ef41Sopenharmony_ci if (lower<T>()) { 37671cb0ef41Sopenharmony_ci ChangeOp(node, simplified()->NumberIsMinusZero()); 37681cb0ef41Sopenharmony_ci } 37691cb0ef41Sopenharmony_ci } else { 37701cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::AnyTagged(), MachineRepresentation::kBit); 37711cb0ef41Sopenharmony_ci } 37721cb0ef41Sopenharmony_ci return; 37731cb0ef41Sopenharmony_ci } 37741cb0ef41Sopenharmony_ci case IrOpcode::kObjectIsNaN: { 37751cb0ef41Sopenharmony_ci Type const input_type = GetUpperBound(node->InputAt(0)); 37761cb0ef41Sopenharmony_ci if (input_type.Is(Type::NaN())) { 37771cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::None(), MachineRepresentation::kBit); 37781cb0ef41Sopenharmony_ci if (lower<T>()) { 37791cb0ef41Sopenharmony_ci DeferReplacement(node, lowering->jsgraph()->Int32Constant(1)); 37801cb0ef41Sopenharmony_ci } 37811cb0ef41Sopenharmony_ci } else if (!input_type.Maybe(Type::NaN())) { 37821cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::Any(), MachineRepresentation::kBit); 37831cb0ef41Sopenharmony_ci if (lower<T>()) { 37841cb0ef41Sopenharmony_ci DeferReplacement(node, lowering->jsgraph()->Int32Constant(0)); 37851cb0ef41Sopenharmony_ci } 37861cb0ef41Sopenharmony_ci } else if (input_type.Is(Type::Number())) { 37871cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::TruncatingFloat64(), 37881cb0ef41Sopenharmony_ci MachineRepresentation::kBit); 37891cb0ef41Sopenharmony_ci if (lower<T>()) { 37901cb0ef41Sopenharmony_ci ChangeOp(node, simplified()->NumberIsNaN()); 37911cb0ef41Sopenharmony_ci } 37921cb0ef41Sopenharmony_ci } else { 37931cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::AnyTagged(), MachineRepresentation::kBit); 37941cb0ef41Sopenharmony_ci } 37951cb0ef41Sopenharmony_ci return; 37961cb0ef41Sopenharmony_ci } 37971cb0ef41Sopenharmony_ci case IrOpcode::kNumberIsNaN: { 37981cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::TruncatingFloat64(), 37991cb0ef41Sopenharmony_ci MachineRepresentation::kBit); 38001cb0ef41Sopenharmony_ci return; 38011cb0ef41Sopenharmony_ci } 38021cb0ef41Sopenharmony_ci case IrOpcode::kObjectIsNonCallable: { 38031cb0ef41Sopenharmony_ci VisitObjectIs<T>(node, Type::NonCallable(), lowering); 38041cb0ef41Sopenharmony_ci return; 38051cb0ef41Sopenharmony_ci } 38061cb0ef41Sopenharmony_ci case IrOpcode::kObjectIsNumber: { 38071cb0ef41Sopenharmony_ci VisitObjectIs<T>(node, Type::Number(), lowering); 38081cb0ef41Sopenharmony_ci return; 38091cb0ef41Sopenharmony_ci } 38101cb0ef41Sopenharmony_ci case IrOpcode::kObjectIsReceiver: { 38111cb0ef41Sopenharmony_ci VisitObjectIs<T>(node, Type::Receiver(), lowering); 38121cb0ef41Sopenharmony_ci return; 38131cb0ef41Sopenharmony_ci } 38141cb0ef41Sopenharmony_ci case IrOpcode::kObjectIsSmi: { 38151cb0ef41Sopenharmony_ci // TODO(turbofan): Optimize based on input representation. 38161cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::AnyTagged(), MachineRepresentation::kBit); 38171cb0ef41Sopenharmony_ci return; 38181cb0ef41Sopenharmony_ci } 38191cb0ef41Sopenharmony_ci case IrOpcode::kObjectIsString: { 38201cb0ef41Sopenharmony_ci VisitObjectIs<T>(node, Type::String(), lowering); 38211cb0ef41Sopenharmony_ci return; 38221cb0ef41Sopenharmony_ci } 38231cb0ef41Sopenharmony_ci case IrOpcode::kObjectIsSymbol: { 38241cb0ef41Sopenharmony_ci VisitObjectIs<T>(node, Type::Symbol(), lowering); 38251cb0ef41Sopenharmony_ci return; 38261cb0ef41Sopenharmony_ci } 38271cb0ef41Sopenharmony_ci case IrOpcode::kObjectIsUndetectable: { 38281cb0ef41Sopenharmony_ci VisitObjectIs<T>(node, Type::Undetectable(), lowering); 38291cb0ef41Sopenharmony_ci return; 38301cb0ef41Sopenharmony_ci } 38311cb0ef41Sopenharmony_ci case IrOpcode::kArgumentsLength: 38321cb0ef41Sopenharmony_ci case IrOpcode::kRestLength: { 38331cb0ef41Sopenharmony_ci SetOutput<T>(node, MachineRepresentation::kTaggedSigned); 38341cb0ef41Sopenharmony_ci return; 38351cb0ef41Sopenharmony_ci } 38361cb0ef41Sopenharmony_ci case IrOpcode::kNewDoubleElements: 38371cb0ef41Sopenharmony_ci case IrOpcode::kNewSmiOrObjectElements: { 38381cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::Word(), 38391cb0ef41Sopenharmony_ci MachineRepresentation::kTaggedPointer); 38401cb0ef41Sopenharmony_ci return; 38411cb0ef41Sopenharmony_ci } 38421cb0ef41Sopenharmony_ci case IrOpcode::kNewArgumentsElements: { 38431cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::TaggedSigned(), 38441cb0ef41Sopenharmony_ci MachineRepresentation::kTaggedPointer); 38451cb0ef41Sopenharmony_ci return; 38461cb0ef41Sopenharmony_ci } 38471cb0ef41Sopenharmony_ci case IrOpcode::kCheckFloat64Hole: { 38481cb0ef41Sopenharmony_ci Type const input_type = TypeOf(node->InputAt(0)); 38491cb0ef41Sopenharmony_ci CheckFloat64HoleMode mode = 38501cb0ef41Sopenharmony_ci CheckFloat64HoleParametersOf(node->op()).mode(); 38511cb0ef41Sopenharmony_ci if (mode == CheckFloat64HoleMode::kAllowReturnHole) { 38521cb0ef41Sopenharmony_ci // If {mode} is allow-return-hole _and_ the {truncation} 38531cb0ef41Sopenharmony_ci // identifies NaN and undefined, we can just pass along 38541cb0ef41Sopenharmony_ci // the {truncation} and completely wipe the {node}. 38551cb0ef41Sopenharmony_ci if (truncation.IsUnused()) return VisitUnused<T>(node); 38561cb0ef41Sopenharmony_ci if (truncation.TruncatesOddballAndBigIntToNumber()) { 38571cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::TruncatingFloat64(), 38581cb0ef41Sopenharmony_ci MachineRepresentation::kFloat64); 38591cb0ef41Sopenharmony_ci if (lower<T>()) DeferReplacement(node, node->InputAt(0)); 38601cb0ef41Sopenharmony_ci return; 38611cb0ef41Sopenharmony_ci } 38621cb0ef41Sopenharmony_ci } 38631cb0ef41Sopenharmony_ci VisitUnop<T>( 38641cb0ef41Sopenharmony_ci node, UseInfo(MachineRepresentation::kFloat64, Truncation::Any()), 38651cb0ef41Sopenharmony_ci MachineRepresentation::kFloat64, Type::Number()); 38661cb0ef41Sopenharmony_ci if (lower<T>() && input_type.Is(Type::Number())) { 38671cb0ef41Sopenharmony_ci DeferReplacement(node, node->InputAt(0)); 38681cb0ef41Sopenharmony_ci } 38691cb0ef41Sopenharmony_ci return; 38701cb0ef41Sopenharmony_ci } 38711cb0ef41Sopenharmony_ci case IrOpcode::kCheckNotTaggedHole: { 38721cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::AnyTagged(), 38731cb0ef41Sopenharmony_ci MachineRepresentation::kTagged); 38741cb0ef41Sopenharmony_ci return; 38751cb0ef41Sopenharmony_ci } 38761cb0ef41Sopenharmony_ci case IrOpcode::kCheckClosure: { 38771cb0ef41Sopenharmony_ci VisitUnop<T>( 38781cb0ef41Sopenharmony_ci node, UseInfo::CheckedHeapObjectAsTaggedPointer(FeedbackSource()), 38791cb0ef41Sopenharmony_ci MachineRepresentation::kTaggedPointer); 38801cb0ef41Sopenharmony_ci return; 38811cb0ef41Sopenharmony_ci } 38821cb0ef41Sopenharmony_ci case IrOpcode::kConvertTaggedHoleToUndefined: { 38831cb0ef41Sopenharmony_ci if (InputIs(node, Type::NumberOrOddball()) && 38841cb0ef41Sopenharmony_ci truncation.IsUsedAsWord32()) { 38851cb0ef41Sopenharmony_ci // Propagate the Word32 truncation. 38861cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::TruncatingWord32(), 38871cb0ef41Sopenharmony_ci MachineRepresentation::kWord32); 38881cb0ef41Sopenharmony_ci if (lower<T>()) DeferReplacement(node, node->InputAt(0)); 38891cb0ef41Sopenharmony_ci } else if (InputIs(node, Type::NumberOrOddball()) && 38901cb0ef41Sopenharmony_ci truncation.TruncatesOddballAndBigIntToNumber()) { 38911cb0ef41Sopenharmony_ci // Propagate the Float64 truncation. 38921cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::TruncatingFloat64(), 38931cb0ef41Sopenharmony_ci MachineRepresentation::kFloat64); 38941cb0ef41Sopenharmony_ci if (lower<T>()) DeferReplacement(node, node->InputAt(0)); 38951cb0ef41Sopenharmony_ci } else if (InputIs(node, Type::NonInternal())) { 38961cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::AnyTagged(), 38971cb0ef41Sopenharmony_ci MachineRepresentation::kTagged); 38981cb0ef41Sopenharmony_ci if (lower<T>()) DeferReplacement(node, node->InputAt(0)); 38991cb0ef41Sopenharmony_ci } else { 39001cb0ef41Sopenharmony_ci // TODO(turbofan): Add a (Tagged) truncation that identifies hole 39011cb0ef41Sopenharmony_ci // and undefined, i.e. for a[i] === obj cases. 39021cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::AnyTagged(), 39031cb0ef41Sopenharmony_ci MachineRepresentation::kTagged); 39041cb0ef41Sopenharmony_ci } 39051cb0ef41Sopenharmony_ci return; 39061cb0ef41Sopenharmony_ci } 39071cb0ef41Sopenharmony_ci case IrOpcode::kCheckEqualsSymbol: 39081cb0ef41Sopenharmony_ci case IrOpcode::kCheckEqualsInternalizedString: 39091cb0ef41Sopenharmony_ci return VisitBinop<T>(node, UseInfo::AnyTagged(), 39101cb0ef41Sopenharmony_ci MachineRepresentation::kNone); 39111cb0ef41Sopenharmony_ci case IrOpcode::kMapGuard: 39121cb0ef41Sopenharmony_ci // Eliminate MapGuard nodes here. 39131cb0ef41Sopenharmony_ci return VisitUnused<T>(node); 39141cb0ef41Sopenharmony_ci case IrOpcode::kCheckMaps: { 39151cb0ef41Sopenharmony_ci CheckMapsParameters const& p = CheckMapsParametersOf(node->op()); 39161cb0ef41Sopenharmony_ci return VisitUnop<T>( 39171cb0ef41Sopenharmony_ci node, UseInfo::CheckedHeapObjectAsTaggedPointer(p.feedback()), 39181cb0ef41Sopenharmony_ci MachineRepresentation::kNone); 39191cb0ef41Sopenharmony_ci } 39201cb0ef41Sopenharmony_ci case IrOpcode::kTransitionElementsKind: { 39211cb0ef41Sopenharmony_ci return VisitUnop<T>( 39221cb0ef41Sopenharmony_ci node, UseInfo::CheckedHeapObjectAsTaggedPointer(FeedbackSource()), 39231cb0ef41Sopenharmony_ci MachineRepresentation::kNone); 39241cb0ef41Sopenharmony_ci } 39251cb0ef41Sopenharmony_ci case IrOpcode::kCompareMaps: 39261cb0ef41Sopenharmony_ci return VisitUnop<T>( 39271cb0ef41Sopenharmony_ci node, UseInfo::CheckedHeapObjectAsTaggedPointer(FeedbackSource()), 39281cb0ef41Sopenharmony_ci MachineRepresentation::kBit); 39291cb0ef41Sopenharmony_ci case IrOpcode::kEnsureWritableFastElements: 39301cb0ef41Sopenharmony_ci return VisitBinop<T>(node, UseInfo::AnyTagged(), 39311cb0ef41Sopenharmony_ci MachineRepresentation::kTaggedPointer); 39321cb0ef41Sopenharmony_ci case IrOpcode::kMaybeGrowFastElements: { 39331cb0ef41Sopenharmony_ci ProcessInput<T>(node, 0, UseInfo::AnyTagged()); // object 39341cb0ef41Sopenharmony_ci ProcessInput<T>(node, 1, UseInfo::AnyTagged()); // elements 39351cb0ef41Sopenharmony_ci ProcessInput<T>(node, 2, UseInfo::TruncatingWord32()); // index 39361cb0ef41Sopenharmony_ci ProcessInput<T>(node, 3, UseInfo::TruncatingWord32()); // length 39371cb0ef41Sopenharmony_ci ProcessRemainingInputs<T>(node, 4); 39381cb0ef41Sopenharmony_ci SetOutput<T>(node, MachineRepresentation::kTaggedPointer); 39391cb0ef41Sopenharmony_ci return; 39401cb0ef41Sopenharmony_ci } 39411cb0ef41Sopenharmony_ci 39421cb0ef41Sopenharmony_ci case IrOpcode::kDateNow: 39431cb0ef41Sopenharmony_ci VisitInputs<T>(node); 39441cb0ef41Sopenharmony_ci return SetOutput<T>(node, MachineRepresentation::kTagged); 39451cb0ef41Sopenharmony_ci case IrOpcode::kFrameState: 39461cb0ef41Sopenharmony_ci return VisitFrameState<T>(FrameState{node}); 39471cb0ef41Sopenharmony_ci case IrOpcode::kStateValues: 39481cb0ef41Sopenharmony_ci return VisitStateValues<T>(node); 39491cb0ef41Sopenharmony_ci case IrOpcode::kObjectState: 39501cb0ef41Sopenharmony_ci return VisitObjectState<T>(node); 39511cb0ef41Sopenharmony_ci case IrOpcode::kObjectId: 39521cb0ef41Sopenharmony_ci return SetOutput<T>(node, MachineRepresentation::kTaggedPointer); 39531cb0ef41Sopenharmony_ci 39541cb0ef41Sopenharmony_ci case IrOpcode::kTypeGuard: { 39551cb0ef41Sopenharmony_ci if (truncation.IsUnused()) return VisitUnused<T>(node); 39561cb0ef41Sopenharmony_ci 39571cb0ef41Sopenharmony_ci // We just get rid of the sigma here, choosing the best representation 39581cb0ef41Sopenharmony_ci // for the sigma's type. 39591cb0ef41Sopenharmony_ci Type type = TypeOf(node); 39601cb0ef41Sopenharmony_ci MachineRepresentation representation = 39611cb0ef41Sopenharmony_ci GetOutputInfoForPhi(node, type, truncation); 39621cb0ef41Sopenharmony_ci 39631cb0ef41Sopenharmony_ci // Here we pretend that the input has the sigma's type for the 39641cb0ef41Sopenharmony_ci // conversion. 39651cb0ef41Sopenharmony_ci UseInfo use(representation, truncation); 39661cb0ef41Sopenharmony_ci if (propagate<T>()) { 39671cb0ef41Sopenharmony_ci EnqueueInput<T>(node, 0, use); 39681cb0ef41Sopenharmony_ci } else if (lower<T>()) { 39691cb0ef41Sopenharmony_ci ConvertInput(node, 0, use, type); 39701cb0ef41Sopenharmony_ci } 39711cb0ef41Sopenharmony_ci ProcessRemainingInputs<T>(node, 1); 39721cb0ef41Sopenharmony_ci SetOutput<T>(node, representation); 39731cb0ef41Sopenharmony_ci return; 39741cb0ef41Sopenharmony_ci } 39751cb0ef41Sopenharmony_ci 39761cb0ef41Sopenharmony_ci case IrOpcode::kFoldConstant: 39771cb0ef41Sopenharmony_ci VisitInputs<T>(node); 39781cb0ef41Sopenharmony_ci return SetOutput<T>(node, MachineRepresentation::kTaggedPointer); 39791cb0ef41Sopenharmony_ci 39801cb0ef41Sopenharmony_ci case IrOpcode::kFinishRegion: 39811cb0ef41Sopenharmony_ci VisitInputs<T>(node); 39821cb0ef41Sopenharmony_ci // Assume the output is tagged pointer. 39831cb0ef41Sopenharmony_ci return SetOutput<T>(node, MachineRepresentation::kTaggedPointer); 39841cb0ef41Sopenharmony_ci 39851cb0ef41Sopenharmony_ci case IrOpcode::kReturn: 39861cb0ef41Sopenharmony_ci VisitReturn<T>(node); 39871cb0ef41Sopenharmony_ci // Assume the output is tagged. 39881cb0ef41Sopenharmony_ci return SetOutput<T>(node, MachineRepresentation::kTagged); 39891cb0ef41Sopenharmony_ci 39901cb0ef41Sopenharmony_ci case IrOpcode::kFindOrderedHashMapEntry: { 39911cb0ef41Sopenharmony_ci Type const key_type = TypeOf(node->InputAt(1)); 39921cb0ef41Sopenharmony_ci if (key_type.Is(Type::Signed32OrMinusZero())) { 39931cb0ef41Sopenharmony_ci VisitBinop<T>(node, UseInfo::AnyTagged(), UseInfo::TruncatingWord32(), 39941cb0ef41Sopenharmony_ci MachineType::PointerRepresentation()); 39951cb0ef41Sopenharmony_ci if (lower<T>()) { 39961cb0ef41Sopenharmony_ci ChangeOp( 39971cb0ef41Sopenharmony_ci node, 39981cb0ef41Sopenharmony_ci lowering->simplified()->FindOrderedHashMapEntryForInt32Key()); 39991cb0ef41Sopenharmony_ci } 40001cb0ef41Sopenharmony_ci } else { 40011cb0ef41Sopenharmony_ci VisitBinop<T>(node, UseInfo::AnyTagged(), 40021cb0ef41Sopenharmony_ci MachineRepresentation::kTaggedSigned); 40031cb0ef41Sopenharmony_ci } 40041cb0ef41Sopenharmony_ci return; 40051cb0ef41Sopenharmony_ci } 40061cb0ef41Sopenharmony_ci 40071cb0ef41Sopenharmony_ci case IrOpcode::kFastApiCall: { 40081cb0ef41Sopenharmony_ci VisitFastApiCall<T>(node, lowering); 40091cb0ef41Sopenharmony_ci return; 40101cb0ef41Sopenharmony_ci } 40111cb0ef41Sopenharmony_ci 40121cb0ef41Sopenharmony_ci // Operators with all inputs tagged and no or tagged output have uniform 40131cb0ef41Sopenharmony_ci // handling. 40141cb0ef41Sopenharmony_ci case IrOpcode::kEnd: 40151cb0ef41Sopenharmony_ci case IrOpcode::kIfSuccess: 40161cb0ef41Sopenharmony_ci case IrOpcode::kIfException: 40171cb0ef41Sopenharmony_ci case IrOpcode::kIfTrue: 40181cb0ef41Sopenharmony_ci case IrOpcode::kIfFalse: 40191cb0ef41Sopenharmony_ci case IrOpcode::kIfValue: 40201cb0ef41Sopenharmony_ci case IrOpcode::kIfDefault: 40211cb0ef41Sopenharmony_ci case IrOpcode::kDeoptimize: 40221cb0ef41Sopenharmony_ci case IrOpcode::kEffectPhi: 40231cb0ef41Sopenharmony_ci case IrOpcode::kTerminate: 40241cb0ef41Sopenharmony_ci case IrOpcode::kCheckpoint: 40251cb0ef41Sopenharmony_ci case IrOpcode::kLoop: 40261cb0ef41Sopenharmony_ci case IrOpcode::kMerge: 40271cb0ef41Sopenharmony_ci case IrOpcode::kThrow: 40281cb0ef41Sopenharmony_ci case IrOpcode::kBeginRegion: 40291cb0ef41Sopenharmony_ci case IrOpcode::kProjection: 40301cb0ef41Sopenharmony_ci case IrOpcode::kOsrValue: 40311cb0ef41Sopenharmony_ci case IrOpcode::kArgumentsElementsState: 40321cb0ef41Sopenharmony_ci case IrOpcode::kArgumentsLengthState: 40331cb0ef41Sopenharmony_ci case IrOpcode::kUnreachable: 40341cb0ef41Sopenharmony_ci case IrOpcode::kRuntimeAbort: 40351cb0ef41Sopenharmony_ci// All JavaScript operators except JSToNumber, JSToNumberConvertBigInt, 40361cb0ef41Sopenharmony_ci// kJSToNumeric and JSWasmCall have uniform handling. 40371cb0ef41Sopenharmony_ci#define OPCODE_CASE(name, ...) case IrOpcode::k##name: 40381cb0ef41Sopenharmony_ci JS_SIMPLE_BINOP_LIST(OPCODE_CASE) 40391cb0ef41Sopenharmony_ci JS_OBJECT_OP_LIST(OPCODE_CASE) 40401cb0ef41Sopenharmony_ci JS_CONTEXT_OP_LIST(OPCODE_CASE) 40411cb0ef41Sopenharmony_ci JS_OTHER_OP_LIST(OPCODE_CASE) 40421cb0ef41Sopenharmony_ci#undef OPCODE_CASE 40431cb0ef41Sopenharmony_ci case IrOpcode::kJSBitwiseNot: 40441cb0ef41Sopenharmony_ci case IrOpcode::kJSDecrement: 40451cb0ef41Sopenharmony_ci case IrOpcode::kJSIncrement: 40461cb0ef41Sopenharmony_ci case IrOpcode::kJSNegate: 40471cb0ef41Sopenharmony_ci case IrOpcode::kJSToLength: 40481cb0ef41Sopenharmony_ci case IrOpcode::kJSToName: 40491cb0ef41Sopenharmony_ci case IrOpcode::kJSToObject: 40501cb0ef41Sopenharmony_ci case IrOpcode::kJSToString: 40511cb0ef41Sopenharmony_ci case IrOpcode::kJSParseInt: 40521cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY 40531cb0ef41Sopenharmony_ci if (node->opcode() == IrOpcode::kJSWasmCall) { 40541cb0ef41Sopenharmony_ci return VisitJSWasmCall<T>(node, lowering); 40551cb0ef41Sopenharmony_ci } 40561cb0ef41Sopenharmony_ci#endif // V8_ENABLE_WEBASSEMBLY 40571cb0ef41Sopenharmony_ci VisitInputs<T>(node); 40581cb0ef41Sopenharmony_ci // Assume the output is tagged. 40591cb0ef41Sopenharmony_ci return SetOutput<T>(node, MachineRepresentation::kTagged); 40601cb0ef41Sopenharmony_ci case IrOpcode::kDeadValue: 40611cb0ef41Sopenharmony_ci ProcessInput<T>(node, 0, UseInfo::Any()); 40621cb0ef41Sopenharmony_ci return SetOutput<T>(node, MachineRepresentation::kNone); 40631cb0ef41Sopenharmony_ci case IrOpcode::kStaticAssert: 40641cb0ef41Sopenharmony_ci DCHECK(TypeOf(node->InputAt(0)).Is(Type::Boolean())); 40651cb0ef41Sopenharmony_ci return VisitUnop<T>(node, UseInfo::Bool(), 40661cb0ef41Sopenharmony_ci MachineRepresentation::kTagged); 40671cb0ef41Sopenharmony_ci case IrOpcode::kAssertType: 40681cb0ef41Sopenharmony_ci return VisitUnop<T>(node, UseInfo::AnyTagged(), 40691cb0ef41Sopenharmony_ci MachineRepresentation::kTagged); 40701cb0ef41Sopenharmony_ci case IrOpcode::kVerifyType: { 40711cb0ef41Sopenharmony_ci Type inputType = TypeOf(node->InputAt(0)); 40721cb0ef41Sopenharmony_ci VisitUnop<T>(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged, 40731cb0ef41Sopenharmony_ci inputType); 40741cb0ef41Sopenharmony_ci if (lower<T>()) { 40751cb0ef41Sopenharmony_ci if (inputType.CanBeAsserted()) { 40761cb0ef41Sopenharmony_ci ChangeOp(node, simplified()->AssertType(inputType)); 40771cb0ef41Sopenharmony_ci } else { 40781cb0ef41Sopenharmony_ci if (!FLAG_fuzzing) { 40791cb0ef41Sopenharmony_ci#ifdef DEBUG 40801cb0ef41Sopenharmony_ci inputType.Print(); 40811cb0ef41Sopenharmony_ci#endif 40821cb0ef41Sopenharmony_ci FATAL("%%VerifyType: unsupported type"); 40831cb0ef41Sopenharmony_ci } 40841cb0ef41Sopenharmony_ci DeferReplacement(node, node->InputAt(0)); 40851cb0ef41Sopenharmony_ci } 40861cb0ef41Sopenharmony_ci } 40871cb0ef41Sopenharmony_ci return; 40881cb0ef41Sopenharmony_ci } 40891cb0ef41Sopenharmony_ci 40901cb0ef41Sopenharmony_ci default: 40911cb0ef41Sopenharmony_ci FATAL( 40921cb0ef41Sopenharmony_ci "Representation inference: unsupported opcode %i (%s), node #%i\n.", 40931cb0ef41Sopenharmony_ci node->opcode(), node->op()->mnemonic(), node->id()); 40941cb0ef41Sopenharmony_ci break; 40951cb0ef41Sopenharmony_ci } 40961cb0ef41Sopenharmony_ci UNREACHABLE(); 40971cb0ef41Sopenharmony_ci } 40981cb0ef41Sopenharmony_ci 40991cb0ef41Sopenharmony_ci void DisconnectFromEffectAndControl(Node* node) { 41001cb0ef41Sopenharmony_ci if (node->op()->EffectInputCount() == 1) { 41011cb0ef41Sopenharmony_ci Node* control = NodeProperties::GetControlInput(node); 41021cb0ef41Sopenharmony_ci Node* effect = NodeProperties::GetEffectInput(node); 41031cb0ef41Sopenharmony_ci ReplaceEffectControlUses(node, effect, control); 41041cb0ef41Sopenharmony_ci } else { 41051cb0ef41Sopenharmony_ci DCHECK_EQ(0, node->op()->EffectInputCount()); 41061cb0ef41Sopenharmony_ci DCHECK_EQ(0, node->op()->ControlOutputCount()); 41071cb0ef41Sopenharmony_ci DCHECK_EQ(0, node->op()->EffectOutputCount()); 41081cb0ef41Sopenharmony_ci } 41091cb0ef41Sopenharmony_ci } 41101cb0ef41Sopenharmony_ci 41111cb0ef41Sopenharmony_ci void DeferReplacement(Node* node, Node* replacement) { 41121cb0ef41Sopenharmony_ci TRACE("defer replacement #%d:%s with #%d:%s\n", node->id(), 41131cb0ef41Sopenharmony_ci node->op()->mnemonic(), replacement->id(), 41141cb0ef41Sopenharmony_ci replacement->op()->mnemonic()); 41151cb0ef41Sopenharmony_ci 41161cb0ef41Sopenharmony_ci DisconnectFromEffectAndControl(node); 41171cb0ef41Sopenharmony_ci node->NullAllInputs(); // Node is now dead. 41181cb0ef41Sopenharmony_ci 41191cb0ef41Sopenharmony_ci replacements_.push_back(node); 41201cb0ef41Sopenharmony_ci replacements_.push_back(replacement); 41211cb0ef41Sopenharmony_ci 41221cb0ef41Sopenharmony_ci NotifyNodeReplaced(node, replacement); 41231cb0ef41Sopenharmony_ci } 41241cb0ef41Sopenharmony_ci 41251cb0ef41Sopenharmony_ci Node* InsertTypeOverrideForVerifier(const Type& type, Node* node) { 41261cb0ef41Sopenharmony_ci if (verification_enabled()) { 41271cb0ef41Sopenharmony_ci DCHECK(!type.IsInvalid()); 41281cb0ef41Sopenharmony_ci node = graph()->NewNode(common()->SLVerifierHint(nullptr, type), node); 41291cb0ef41Sopenharmony_ci verifier_->RecordHint(node); 41301cb0ef41Sopenharmony_ci } 41311cb0ef41Sopenharmony_ci return node; 41321cb0ef41Sopenharmony_ci } 41331cb0ef41Sopenharmony_ci 41341cb0ef41Sopenharmony_ci void ChangeToSemanticsHintForVerifier(Node* node, const Operator* semantics) { 41351cb0ef41Sopenharmony_ci DCHECK_EQ(node->op()->ValueInputCount(), 1); 41361cb0ef41Sopenharmony_ci DCHECK_EQ(node->op()->EffectInputCount(), 0); 41371cb0ef41Sopenharmony_ci DCHECK_EQ(node->op()->ControlInputCount(), 0); 41381cb0ef41Sopenharmony_ci if (verification_enabled()) { 41391cb0ef41Sopenharmony_ci ChangeOp(node, common()->SLVerifierHint(semantics, base::nullopt)); 41401cb0ef41Sopenharmony_ci verifier_->RecordHint(node); 41411cb0ef41Sopenharmony_ci } else { 41421cb0ef41Sopenharmony_ci DeferReplacement(node, node->InputAt(0)); 41431cb0ef41Sopenharmony_ci } 41441cb0ef41Sopenharmony_ci } 41451cb0ef41Sopenharmony_ci 41461cb0ef41Sopenharmony_ci private: 41471cb0ef41Sopenharmony_ci void ChangeOp(Node* node, const Operator* new_op) { 41481cb0ef41Sopenharmony_ci compiler::NodeProperties::ChangeOp(node, new_op); 41491cb0ef41Sopenharmony_ci 41501cb0ef41Sopenharmony_ci if (V8_UNLIKELY(observe_node_manager_ != nullptr)) 41511cb0ef41Sopenharmony_ci observe_node_manager_->OnNodeChanged(kSimplifiedLoweringReducerName, node, 41521cb0ef41Sopenharmony_ci node); 41531cb0ef41Sopenharmony_ci } 41541cb0ef41Sopenharmony_ci 41551cb0ef41Sopenharmony_ci void NotifyNodeReplaced(Node* node, Node* replacement) { 41561cb0ef41Sopenharmony_ci if (V8_UNLIKELY(observe_node_manager_ != nullptr)) 41571cb0ef41Sopenharmony_ci observe_node_manager_->OnNodeChanged(kSimplifiedLoweringReducerName, node, 41581cb0ef41Sopenharmony_ci replacement); 41591cb0ef41Sopenharmony_ci } 41601cb0ef41Sopenharmony_ci 41611cb0ef41Sopenharmony_ci JSGraph* jsgraph_; 41621cb0ef41Sopenharmony_ci JSHeapBroker* broker_; 41631cb0ef41Sopenharmony_ci Zone* zone_; // Temporary zone. 41641cb0ef41Sopenharmony_ci // Map from node to its uses that might need to be revisited. 41651cb0ef41Sopenharmony_ci ZoneMap<Node*, ZoneVector<Node*>> might_need_revisit_; 41661cb0ef41Sopenharmony_ci size_t count_; // number of nodes in the graph 41671cb0ef41Sopenharmony_ci ZoneVector<NodeInfo> info_; // node id -> usage information 41681cb0ef41Sopenharmony_ci#ifdef DEBUG 41691cb0ef41Sopenharmony_ci ZoneVector<InputUseInfos> node_input_use_infos_; // Debug information about 41701cb0ef41Sopenharmony_ci // requirements on inputs. 41711cb0ef41Sopenharmony_ci#endif // DEBUG 41721cb0ef41Sopenharmony_ci NodeVector replacements_; // replacements to be done after lowering 41731cb0ef41Sopenharmony_ci RepresentationChanger* changer_; // for inserting representation changes 41741cb0ef41Sopenharmony_ci ZoneQueue<Node*> revisit_queue_; // Queue for revisiting nodes. 41751cb0ef41Sopenharmony_ci 41761cb0ef41Sopenharmony_ci struct NodeState { 41771cb0ef41Sopenharmony_ci Node* node; 41781cb0ef41Sopenharmony_ci int input_index; 41791cb0ef41Sopenharmony_ci }; 41801cb0ef41Sopenharmony_ci NodeVector traversal_nodes_; // Order in which to traverse the nodes. 41811cb0ef41Sopenharmony_ci // TODO(danno): RepresentationSelector shouldn't know anything about the 41821cb0ef41Sopenharmony_ci // source positions table, but must for now since there currently is no other 41831cb0ef41Sopenharmony_ci // way to pass down source position information to nodes created during 41841cb0ef41Sopenharmony_ci // lowering. Once this phase becomes a vanilla reducer, it should get source 41851cb0ef41Sopenharmony_ci // position information via the SourcePositionWrapper like all other reducers. 41861cb0ef41Sopenharmony_ci SourcePositionTable* source_positions_; 41871cb0ef41Sopenharmony_ci NodeOriginTable* node_origins_; 41881cb0ef41Sopenharmony_ci TypeCache const* type_cache_; 41891cb0ef41Sopenharmony_ci OperationTyper op_typer_; // helper for the feedback typer 41901cb0ef41Sopenharmony_ci TickCounter* const tick_counter_; 41911cb0ef41Sopenharmony_ci Linkage* const linkage_; 41921cb0ef41Sopenharmony_ci ObserveNodeManager* const observe_node_manager_; 41931cb0ef41Sopenharmony_ci SimplifiedLoweringVerifier* verifier_; // Used to verify output graph. 41941cb0ef41Sopenharmony_ci 41951cb0ef41Sopenharmony_ci NodeInfo* GetInfo(Node* node) { 41961cb0ef41Sopenharmony_ci DCHECK(node->id() < count_); 41971cb0ef41Sopenharmony_ci return &info_[node->id()]; 41981cb0ef41Sopenharmony_ci } 41991cb0ef41Sopenharmony_ci Zone* zone() { return zone_; } 42001cb0ef41Sopenharmony_ci Zone* graph_zone() { return jsgraph_->zone(); } 42011cb0ef41Sopenharmony_ci Linkage* linkage() { return linkage_; } 42021cb0ef41Sopenharmony_ci}; 42031cb0ef41Sopenharmony_ci 42041cb0ef41Sopenharmony_ci// Template specializations 42051cb0ef41Sopenharmony_ci 42061cb0ef41Sopenharmony_ci// Enqueue {use_node}'s {index} input if the {use_info} contains new information 42071cb0ef41Sopenharmony_ci// for that input node. 42081cb0ef41Sopenharmony_citemplate <> 42091cb0ef41Sopenharmony_civoid RepresentationSelector::EnqueueInput<PROPAGATE>(Node* use_node, int index, 42101cb0ef41Sopenharmony_ci UseInfo use_info) { 42111cb0ef41Sopenharmony_ci Node* node = use_node->InputAt(index); 42121cb0ef41Sopenharmony_ci NodeInfo* info = GetInfo(node); 42131cb0ef41Sopenharmony_ci#ifdef DEBUG 42141cb0ef41Sopenharmony_ci // Check monotonicity of input requirements. 42151cb0ef41Sopenharmony_ci node_input_use_infos_[use_node->id()].SetAndCheckInput(use_node, index, 42161cb0ef41Sopenharmony_ci use_info); 42171cb0ef41Sopenharmony_ci#endif // DEBUG 42181cb0ef41Sopenharmony_ci if (info->unvisited()) { 42191cb0ef41Sopenharmony_ci info->AddUse(use_info); 42201cb0ef41Sopenharmony_ci TRACE(" initial #%i: %s\n", node->id(), info->truncation().description()); 42211cb0ef41Sopenharmony_ci return; 42221cb0ef41Sopenharmony_ci } 42231cb0ef41Sopenharmony_ci TRACE(" queue #%i?: %s\n", node->id(), info->truncation().description()); 42241cb0ef41Sopenharmony_ci if (info->AddUse(use_info)) { 42251cb0ef41Sopenharmony_ci // New usage information for the node is available. 42261cb0ef41Sopenharmony_ci if (!info->queued()) { 42271cb0ef41Sopenharmony_ci DCHECK(info->visited()); 42281cb0ef41Sopenharmony_ci revisit_queue_.push(node); 42291cb0ef41Sopenharmony_ci info->set_queued(); 42301cb0ef41Sopenharmony_ci TRACE(" added: %s\n", info->truncation().description()); 42311cb0ef41Sopenharmony_ci } else { 42321cb0ef41Sopenharmony_ci TRACE(" inqueue: %s\n", info->truncation().description()); 42331cb0ef41Sopenharmony_ci } 42341cb0ef41Sopenharmony_ci } 42351cb0ef41Sopenharmony_ci} 42361cb0ef41Sopenharmony_ci 42371cb0ef41Sopenharmony_citemplate <> 42381cb0ef41Sopenharmony_civoid RepresentationSelector::SetOutput<PROPAGATE>( 42391cb0ef41Sopenharmony_ci Node* node, MachineRepresentation representation, Type restriction_type) { 42401cb0ef41Sopenharmony_ci NodeInfo* const info = GetInfo(node); 42411cb0ef41Sopenharmony_ci info->set_restriction_type(restriction_type); 42421cb0ef41Sopenharmony_ci} 42431cb0ef41Sopenharmony_ci 42441cb0ef41Sopenharmony_citemplate <> 42451cb0ef41Sopenharmony_civoid RepresentationSelector::SetOutput<RETYPE>( 42461cb0ef41Sopenharmony_ci Node* node, MachineRepresentation representation, Type restriction_type) { 42471cb0ef41Sopenharmony_ci NodeInfo* const info = GetInfo(node); 42481cb0ef41Sopenharmony_ci DCHECK(restriction_type.Is(info->restriction_type())); 42491cb0ef41Sopenharmony_ci info->set_output(representation); 42501cb0ef41Sopenharmony_ci} 42511cb0ef41Sopenharmony_ci 42521cb0ef41Sopenharmony_citemplate <> 42531cb0ef41Sopenharmony_civoid RepresentationSelector::SetOutput<LOWER>( 42541cb0ef41Sopenharmony_ci Node* node, MachineRepresentation representation, Type restriction_type) { 42551cb0ef41Sopenharmony_ci NodeInfo* const info = GetInfo(node); 42561cb0ef41Sopenharmony_ci DCHECK_EQ(info->representation(), representation); 42571cb0ef41Sopenharmony_ci DCHECK(restriction_type.Is(info->restriction_type())); 42581cb0ef41Sopenharmony_ci USE(info); 42591cb0ef41Sopenharmony_ci} 42601cb0ef41Sopenharmony_ci 42611cb0ef41Sopenharmony_citemplate <> 42621cb0ef41Sopenharmony_civoid RepresentationSelector::ProcessInput<PROPAGATE>(Node* node, int index, 42631cb0ef41Sopenharmony_ci UseInfo use) { 42641cb0ef41Sopenharmony_ci DCHECK_IMPLIES(use.type_check() != TypeCheckKind::kNone, 42651cb0ef41Sopenharmony_ci !node->op()->HasProperty(Operator::kNoDeopt) && 42661cb0ef41Sopenharmony_ci node->op()->EffectInputCount() > 0); 42671cb0ef41Sopenharmony_ci EnqueueInput<PROPAGATE>(node, index, use); 42681cb0ef41Sopenharmony_ci} 42691cb0ef41Sopenharmony_ci 42701cb0ef41Sopenharmony_citemplate <> 42711cb0ef41Sopenharmony_civoid RepresentationSelector::ProcessInput<RETYPE>(Node* node, int index, 42721cb0ef41Sopenharmony_ci UseInfo use) { 42731cb0ef41Sopenharmony_ci DCHECK_IMPLIES(use.type_check() != TypeCheckKind::kNone, 42741cb0ef41Sopenharmony_ci !node->op()->HasProperty(Operator::kNoDeopt) && 42751cb0ef41Sopenharmony_ci node->op()->EffectInputCount() > 0); 42761cb0ef41Sopenharmony_ci} 42771cb0ef41Sopenharmony_ci 42781cb0ef41Sopenharmony_citemplate <> 42791cb0ef41Sopenharmony_civoid RepresentationSelector::ProcessInput<LOWER>(Node* node, int index, 42801cb0ef41Sopenharmony_ci UseInfo use) { 42811cb0ef41Sopenharmony_ci DCHECK_IMPLIES(use.type_check() != TypeCheckKind::kNone, 42821cb0ef41Sopenharmony_ci !node->op()->HasProperty(Operator::kNoDeopt) && 42831cb0ef41Sopenharmony_ci node->op()->EffectInputCount() > 0); 42841cb0ef41Sopenharmony_ci ConvertInput(node, index, use); 42851cb0ef41Sopenharmony_ci} 42861cb0ef41Sopenharmony_ci 42871cb0ef41Sopenharmony_citemplate <> 42881cb0ef41Sopenharmony_civoid RepresentationSelector::ProcessRemainingInputs<PROPAGATE>(Node* node, 42891cb0ef41Sopenharmony_ci int index) { 42901cb0ef41Sopenharmony_ci DCHECK_GE(index, NodeProperties::PastContextIndex(node)); 42911cb0ef41Sopenharmony_ci 42921cb0ef41Sopenharmony_ci // Enqueue other inputs (effects, control). 42931cb0ef41Sopenharmony_ci for (int i = std::max(index, NodeProperties::FirstEffectIndex(node)); 42941cb0ef41Sopenharmony_ci i < node->InputCount(); ++i) { 42951cb0ef41Sopenharmony_ci EnqueueInput<PROPAGATE>(node, i); 42961cb0ef41Sopenharmony_ci } 42971cb0ef41Sopenharmony_ci} 42981cb0ef41Sopenharmony_ci 42991cb0ef41Sopenharmony_ci// The default, most general visitation case. For {node}, process all value, 43001cb0ef41Sopenharmony_ci// context, frame state, effect, and control inputs, assuming that value 43011cb0ef41Sopenharmony_ci// inputs should have {kRepTagged} representation and can observe all output 43021cb0ef41Sopenharmony_ci// values {kTypeAny}. 43031cb0ef41Sopenharmony_citemplate <> 43041cb0ef41Sopenharmony_civoid RepresentationSelector::VisitInputs<PROPAGATE>(Node* node) { 43051cb0ef41Sopenharmony_ci int first_effect_index = NodeProperties::FirstEffectIndex(node); 43061cb0ef41Sopenharmony_ci // Visit value, context and frame state inputs as tagged. 43071cb0ef41Sopenharmony_ci for (int i = 0; i < first_effect_index; i++) { 43081cb0ef41Sopenharmony_ci ProcessInput<PROPAGATE>(node, i, UseInfo::AnyTagged()); 43091cb0ef41Sopenharmony_ci } 43101cb0ef41Sopenharmony_ci // Only enqueue other inputs (effects, control). 43111cb0ef41Sopenharmony_ci for (int i = first_effect_index; i < node->InputCount(); i++) { 43121cb0ef41Sopenharmony_ci EnqueueInput<PROPAGATE>(node, i); 43131cb0ef41Sopenharmony_ci } 43141cb0ef41Sopenharmony_ci} 43151cb0ef41Sopenharmony_ci 43161cb0ef41Sopenharmony_citemplate <> 43171cb0ef41Sopenharmony_civoid RepresentationSelector::VisitInputs<LOWER>(Node* node) { 43181cb0ef41Sopenharmony_ci int first_effect_index = NodeProperties::FirstEffectIndex(node); 43191cb0ef41Sopenharmony_ci // Visit value, context and frame state inputs as tagged. 43201cb0ef41Sopenharmony_ci for (int i = 0; i < first_effect_index; i++) { 43211cb0ef41Sopenharmony_ci ProcessInput<LOWER>(node, i, UseInfo::AnyTagged()); 43221cb0ef41Sopenharmony_ci } 43231cb0ef41Sopenharmony_ci} 43241cb0ef41Sopenharmony_ci 43251cb0ef41Sopenharmony_citemplate <> 43261cb0ef41Sopenharmony_civoid RepresentationSelector::InsertUnreachableIfNecessary<LOWER>(Node* node) { 43271cb0ef41Sopenharmony_ci // If the node is effectful and it produces an impossible value, then we 43281cb0ef41Sopenharmony_ci // insert Unreachable node after it. 43291cb0ef41Sopenharmony_ci if (node->op()->ValueOutputCount() > 0 && 43301cb0ef41Sopenharmony_ci node->op()->EffectOutputCount() > 0 && 43311cb0ef41Sopenharmony_ci node->opcode() != IrOpcode::kUnreachable && TypeOf(node).IsNone()) { 43321cb0ef41Sopenharmony_ci Node* control = (node->op()->ControlOutputCount() == 0) 43331cb0ef41Sopenharmony_ci ? NodeProperties::GetControlInput(node, 0) 43341cb0ef41Sopenharmony_ci : NodeProperties::FindSuccessfulControlProjection(node); 43351cb0ef41Sopenharmony_ci 43361cb0ef41Sopenharmony_ci Node* unreachable = 43371cb0ef41Sopenharmony_ci graph()->NewNode(common()->Unreachable(), node, control); 43381cb0ef41Sopenharmony_ci 43391cb0ef41Sopenharmony_ci // Insert unreachable node and replace all the effect uses of the {node} 43401cb0ef41Sopenharmony_ci // with the new unreachable node. 43411cb0ef41Sopenharmony_ci for (Edge edge : node->use_edges()) { 43421cb0ef41Sopenharmony_ci if (!NodeProperties::IsEffectEdge(edge)) continue; 43431cb0ef41Sopenharmony_ci // Make sure to not overwrite the unreachable node's input. That would 43441cb0ef41Sopenharmony_ci // create a cycle. 43451cb0ef41Sopenharmony_ci if (edge.from() == unreachable) continue; 43461cb0ef41Sopenharmony_ci // Avoid messing up the exceptional path. 43471cb0ef41Sopenharmony_ci if (edge.from()->opcode() == IrOpcode::kIfException) { 43481cb0ef41Sopenharmony_ci DCHECK(!node->op()->HasProperty(Operator::kNoThrow)); 43491cb0ef41Sopenharmony_ci DCHECK_EQ(NodeProperties::GetControlInput(edge.from()), node); 43501cb0ef41Sopenharmony_ci continue; 43511cb0ef41Sopenharmony_ci } 43521cb0ef41Sopenharmony_ci 43531cb0ef41Sopenharmony_ci edge.UpdateTo(unreachable); 43541cb0ef41Sopenharmony_ci } 43551cb0ef41Sopenharmony_ci } 43561cb0ef41Sopenharmony_ci} 43571cb0ef41Sopenharmony_ci 43581cb0ef41Sopenharmony_ciSimplifiedLowering::SimplifiedLowering( 43591cb0ef41Sopenharmony_ci JSGraph* jsgraph, JSHeapBroker* broker, Zone* zone, 43601cb0ef41Sopenharmony_ci SourcePositionTable* source_positions, NodeOriginTable* node_origins, 43611cb0ef41Sopenharmony_ci TickCounter* tick_counter, Linkage* linkage, OptimizedCompilationInfo* info, 43621cb0ef41Sopenharmony_ci ObserveNodeManager* observe_node_manager) 43631cb0ef41Sopenharmony_ci : jsgraph_(jsgraph), 43641cb0ef41Sopenharmony_ci broker_(broker), 43651cb0ef41Sopenharmony_ci zone_(zone), 43661cb0ef41Sopenharmony_ci type_cache_(TypeCache::Get()), 43671cb0ef41Sopenharmony_ci source_positions_(source_positions), 43681cb0ef41Sopenharmony_ci node_origins_(node_origins), 43691cb0ef41Sopenharmony_ci tick_counter_(tick_counter), 43701cb0ef41Sopenharmony_ci linkage_(linkage), 43711cb0ef41Sopenharmony_ci info_(info), 43721cb0ef41Sopenharmony_ci observe_node_manager_(observe_node_manager) {} 43731cb0ef41Sopenharmony_ci 43741cb0ef41Sopenharmony_civoid SimplifiedLowering::LowerAllNodes() { 43751cb0ef41Sopenharmony_ci SimplifiedLoweringVerifier* verifier = nullptr; 43761cb0ef41Sopenharmony_ci if (FLAG_verify_simplified_lowering) { 43771cb0ef41Sopenharmony_ci verifier = zone_->New<SimplifiedLoweringVerifier>(zone_, graph()); 43781cb0ef41Sopenharmony_ci } 43791cb0ef41Sopenharmony_ci RepresentationChanger changer(jsgraph(), broker_, verifier); 43801cb0ef41Sopenharmony_ci RepresentationSelector selector( 43811cb0ef41Sopenharmony_ci jsgraph(), broker_, zone_, &changer, source_positions_, node_origins_, 43821cb0ef41Sopenharmony_ci tick_counter_, linkage_, observe_node_manager_, verifier); 43831cb0ef41Sopenharmony_ci selector.Run(this); 43841cb0ef41Sopenharmony_ci} 43851cb0ef41Sopenharmony_ci 43861cb0ef41Sopenharmony_civoid SimplifiedLowering::DoJSToNumberOrNumericTruncatesToFloat64( 43871cb0ef41Sopenharmony_ci Node* node, RepresentationSelector* selector) { 43881cb0ef41Sopenharmony_ci DCHECK(node->opcode() == IrOpcode::kJSToNumber || 43891cb0ef41Sopenharmony_ci node->opcode() == IrOpcode::kJSToNumberConvertBigInt || 43901cb0ef41Sopenharmony_ci node->opcode() == IrOpcode::kJSToNumeric); 43911cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 43921cb0ef41Sopenharmony_ci Node* context = node->InputAt(1); 43931cb0ef41Sopenharmony_ci Node* frame_state = node->InputAt(2); 43941cb0ef41Sopenharmony_ci Node* effect = node->InputAt(3); 43951cb0ef41Sopenharmony_ci Node* control = node->InputAt(4); 43961cb0ef41Sopenharmony_ci 43971cb0ef41Sopenharmony_ci Node* check0 = graph()->NewNode(simplified()->ObjectIsSmi(), value); 43981cb0ef41Sopenharmony_ci Node* branch0 = 43991cb0ef41Sopenharmony_ci graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control); 44001cb0ef41Sopenharmony_ci 44011cb0ef41Sopenharmony_ci Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0); 44021cb0ef41Sopenharmony_ci Node* etrue0 = effect; 44031cb0ef41Sopenharmony_ci Node* vtrue0; 44041cb0ef41Sopenharmony_ci { 44051cb0ef41Sopenharmony_ci vtrue0 = graph()->NewNode(simplified()->ChangeTaggedSignedToInt32(), value); 44061cb0ef41Sopenharmony_ci vtrue0 = graph()->NewNode(machine()->ChangeInt32ToFloat64(), vtrue0); 44071cb0ef41Sopenharmony_ci } 44081cb0ef41Sopenharmony_ci 44091cb0ef41Sopenharmony_ci Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0); 44101cb0ef41Sopenharmony_ci Node* efalse0 = effect; 44111cb0ef41Sopenharmony_ci Node* vfalse0; 44121cb0ef41Sopenharmony_ci { 44131cb0ef41Sopenharmony_ci Operator const* op = 44141cb0ef41Sopenharmony_ci node->opcode() == IrOpcode::kJSToNumber 44151cb0ef41Sopenharmony_ci ? (node->opcode() == IrOpcode::kJSToNumberConvertBigInt 44161cb0ef41Sopenharmony_ci ? ToNumberConvertBigIntOperator() 44171cb0ef41Sopenharmony_ci : ToNumberOperator()) 44181cb0ef41Sopenharmony_ci : ToNumericOperator(); 44191cb0ef41Sopenharmony_ci Node* code = node->opcode() == IrOpcode::kJSToNumber 44201cb0ef41Sopenharmony_ci ? ToNumberCode() 44211cb0ef41Sopenharmony_ci : (node->opcode() == IrOpcode::kJSToNumberConvertBigInt 44221cb0ef41Sopenharmony_ci ? ToNumberConvertBigIntCode() 44231cb0ef41Sopenharmony_ci : ToNumericCode()); 44241cb0ef41Sopenharmony_ci vfalse0 = efalse0 = if_false0 = graph()->NewNode( 44251cb0ef41Sopenharmony_ci op, code, value, context, frame_state, efalse0, if_false0); 44261cb0ef41Sopenharmony_ci 44271cb0ef41Sopenharmony_ci // Update potential {IfException} uses of {node} to point to the above 44281cb0ef41Sopenharmony_ci // stub call node instead. 44291cb0ef41Sopenharmony_ci Node* on_exception = nullptr; 44301cb0ef41Sopenharmony_ci if (NodeProperties::IsExceptionalCall(node, &on_exception)) { 44311cb0ef41Sopenharmony_ci NodeProperties::ReplaceControlInput(on_exception, vfalse0); 44321cb0ef41Sopenharmony_ci NodeProperties::ReplaceEffectInput(on_exception, efalse0); 44331cb0ef41Sopenharmony_ci if_false0 = graph()->NewNode(common()->IfSuccess(), vfalse0); 44341cb0ef41Sopenharmony_ci } 44351cb0ef41Sopenharmony_ci 44361cb0ef41Sopenharmony_ci Node* check1 = graph()->NewNode(simplified()->ObjectIsSmi(), vfalse0); 44371cb0ef41Sopenharmony_ci Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_false0); 44381cb0ef41Sopenharmony_ci 44391cb0ef41Sopenharmony_ci Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); 44401cb0ef41Sopenharmony_ci Node* etrue1 = efalse0; 44411cb0ef41Sopenharmony_ci Node* vtrue1; 44421cb0ef41Sopenharmony_ci { 44431cb0ef41Sopenharmony_ci vtrue1 = 44441cb0ef41Sopenharmony_ci graph()->NewNode(simplified()->ChangeTaggedSignedToInt32(), vfalse0); 44451cb0ef41Sopenharmony_ci vtrue1 = graph()->NewNode(machine()->ChangeInt32ToFloat64(), vtrue1); 44461cb0ef41Sopenharmony_ci } 44471cb0ef41Sopenharmony_ci 44481cb0ef41Sopenharmony_ci Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); 44491cb0ef41Sopenharmony_ci Node* efalse1 = efalse0; 44501cb0ef41Sopenharmony_ci Node* vfalse1; 44511cb0ef41Sopenharmony_ci { 44521cb0ef41Sopenharmony_ci vfalse1 = efalse1 = graph()->NewNode( 44531cb0ef41Sopenharmony_ci simplified()->LoadField(AccessBuilder::ForHeapNumberValue()), efalse0, 44541cb0ef41Sopenharmony_ci efalse1, if_false1); 44551cb0ef41Sopenharmony_ci } 44561cb0ef41Sopenharmony_ci 44571cb0ef41Sopenharmony_ci if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1); 44581cb0ef41Sopenharmony_ci efalse0 = 44591cb0ef41Sopenharmony_ci graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, if_false0); 44601cb0ef41Sopenharmony_ci vfalse0 = 44611cb0ef41Sopenharmony_ci graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2), 44621cb0ef41Sopenharmony_ci vtrue1, vfalse1, if_false0); 44631cb0ef41Sopenharmony_ci } 44641cb0ef41Sopenharmony_ci 44651cb0ef41Sopenharmony_ci control = graph()->NewNode(common()->Merge(2), if_true0, if_false0); 44661cb0ef41Sopenharmony_ci effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control); 44671cb0ef41Sopenharmony_ci value = graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2), 44681cb0ef41Sopenharmony_ci vtrue0, vfalse0, control); 44691cb0ef41Sopenharmony_ci 44701cb0ef41Sopenharmony_ci // Replace effect and control uses appropriately. 44711cb0ef41Sopenharmony_ci for (Edge edge : node->use_edges()) { 44721cb0ef41Sopenharmony_ci if (NodeProperties::IsControlEdge(edge)) { 44731cb0ef41Sopenharmony_ci if (edge.from()->opcode() == IrOpcode::kIfSuccess) { 44741cb0ef41Sopenharmony_ci edge.from()->ReplaceUses(control); 44751cb0ef41Sopenharmony_ci edge.from()->Kill(); 44761cb0ef41Sopenharmony_ci } else { 44771cb0ef41Sopenharmony_ci DCHECK_NE(IrOpcode::kIfException, edge.from()->opcode()); 44781cb0ef41Sopenharmony_ci edge.UpdateTo(control); 44791cb0ef41Sopenharmony_ci } 44801cb0ef41Sopenharmony_ci } else if (NodeProperties::IsEffectEdge(edge)) { 44811cb0ef41Sopenharmony_ci edge.UpdateTo(effect); 44821cb0ef41Sopenharmony_ci } 44831cb0ef41Sopenharmony_ci } 44841cb0ef41Sopenharmony_ci 44851cb0ef41Sopenharmony_ci selector->DeferReplacement(node, value); 44861cb0ef41Sopenharmony_ci} 44871cb0ef41Sopenharmony_ci 44881cb0ef41Sopenharmony_civoid SimplifiedLowering::DoJSToNumberOrNumericTruncatesToWord32( 44891cb0ef41Sopenharmony_ci Node* node, RepresentationSelector* selector) { 44901cb0ef41Sopenharmony_ci DCHECK(node->opcode() == IrOpcode::kJSToNumber || 44911cb0ef41Sopenharmony_ci node->opcode() == IrOpcode::kJSToNumberConvertBigInt || 44921cb0ef41Sopenharmony_ci node->opcode() == IrOpcode::kJSToNumeric); 44931cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 44941cb0ef41Sopenharmony_ci Node* context = node->InputAt(1); 44951cb0ef41Sopenharmony_ci Node* frame_state = node->InputAt(2); 44961cb0ef41Sopenharmony_ci Node* effect = node->InputAt(3); 44971cb0ef41Sopenharmony_ci Node* control = node->InputAt(4); 44981cb0ef41Sopenharmony_ci 44991cb0ef41Sopenharmony_ci Node* check0 = graph()->NewNode(simplified()->ObjectIsSmi(), value); 45001cb0ef41Sopenharmony_ci Node* branch0 = 45011cb0ef41Sopenharmony_ci graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control); 45021cb0ef41Sopenharmony_ci 45031cb0ef41Sopenharmony_ci Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0); 45041cb0ef41Sopenharmony_ci Node* etrue0 = effect; 45051cb0ef41Sopenharmony_ci Node* vtrue0 = 45061cb0ef41Sopenharmony_ci graph()->NewNode(simplified()->ChangeTaggedSignedToInt32(), value); 45071cb0ef41Sopenharmony_ci 45081cb0ef41Sopenharmony_ci Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0); 45091cb0ef41Sopenharmony_ci Node* efalse0 = effect; 45101cb0ef41Sopenharmony_ci Node* vfalse0; 45111cb0ef41Sopenharmony_ci { 45121cb0ef41Sopenharmony_ci Operator const* op = 45131cb0ef41Sopenharmony_ci node->opcode() == IrOpcode::kJSToNumber 45141cb0ef41Sopenharmony_ci ? (node->opcode() == IrOpcode::kJSToNumberConvertBigInt 45151cb0ef41Sopenharmony_ci ? ToNumberConvertBigIntOperator() 45161cb0ef41Sopenharmony_ci : ToNumberOperator()) 45171cb0ef41Sopenharmony_ci : ToNumericOperator(); 45181cb0ef41Sopenharmony_ci Node* code = node->opcode() == IrOpcode::kJSToNumber 45191cb0ef41Sopenharmony_ci ? ToNumberCode() 45201cb0ef41Sopenharmony_ci : (node->opcode() == IrOpcode::kJSToNumberConvertBigInt 45211cb0ef41Sopenharmony_ci ? ToNumberConvertBigIntCode() 45221cb0ef41Sopenharmony_ci : ToNumericCode()); 45231cb0ef41Sopenharmony_ci vfalse0 = efalse0 = if_false0 = graph()->NewNode( 45241cb0ef41Sopenharmony_ci op, code, value, context, frame_state, efalse0, if_false0); 45251cb0ef41Sopenharmony_ci 45261cb0ef41Sopenharmony_ci // Update potential {IfException} uses of {node} to point to the above 45271cb0ef41Sopenharmony_ci // stub call node instead. 45281cb0ef41Sopenharmony_ci Node* on_exception = nullptr; 45291cb0ef41Sopenharmony_ci if (NodeProperties::IsExceptionalCall(node, &on_exception)) { 45301cb0ef41Sopenharmony_ci NodeProperties::ReplaceControlInput(on_exception, vfalse0); 45311cb0ef41Sopenharmony_ci NodeProperties::ReplaceEffectInput(on_exception, efalse0); 45321cb0ef41Sopenharmony_ci if_false0 = graph()->NewNode(common()->IfSuccess(), vfalse0); 45331cb0ef41Sopenharmony_ci } 45341cb0ef41Sopenharmony_ci 45351cb0ef41Sopenharmony_ci Node* check1 = graph()->NewNode(simplified()->ObjectIsSmi(), vfalse0); 45361cb0ef41Sopenharmony_ci Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_false0); 45371cb0ef41Sopenharmony_ci 45381cb0ef41Sopenharmony_ci Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); 45391cb0ef41Sopenharmony_ci Node* etrue1 = efalse0; 45401cb0ef41Sopenharmony_ci Node* vtrue1 = 45411cb0ef41Sopenharmony_ci graph()->NewNode(simplified()->ChangeTaggedSignedToInt32(), vfalse0); 45421cb0ef41Sopenharmony_ci 45431cb0ef41Sopenharmony_ci Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); 45441cb0ef41Sopenharmony_ci Node* efalse1 = efalse0; 45451cb0ef41Sopenharmony_ci Node* vfalse1; 45461cb0ef41Sopenharmony_ci { 45471cb0ef41Sopenharmony_ci vfalse1 = efalse1 = graph()->NewNode( 45481cb0ef41Sopenharmony_ci simplified()->LoadField(AccessBuilder::ForHeapNumberValue()), efalse0, 45491cb0ef41Sopenharmony_ci efalse1, if_false1); 45501cb0ef41Sopenharmony_ci vfalse1 = graph()->NewNode(machine()->TruncateFloat64ToWord32(), vfalse1); 45511cb0ef41Sopenharmony_ci } 45521cb0ef41Sopenharmony_ci 45531cb0ef41Sopenharmony_ci if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1); 45541cb0ef41Sopenharmony_ci efalse0 = 45551cb0ef41Sopenharmony_ci graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, if_false0); 45561cb0ef41Sopenharmony_ci vfalse0 = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2), 45571cb0ef41Sopenharmony_ci vtrue1, vfalse1, if_false0); 45581cb0ef41Sopenharmony_ci } 45591cb0ef41Sopenharmony_ci 45601cb0ef41Sopenharmony_ci control = graph()->NewNode(common()->Merge(2), if_true0, if_false0); 45611cb0ef41Sopenharmony_ci effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control); 45621cb0ef41Sopenharmony_ci value = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2), 45631cb0ef41Sopenharmony_ci vtrue0, vfalse0, control); 45641cb0ef41Sopenharmony_ci 45651cb0ef41Sopenharmony_ci // Replace effect and control uses appropriately. 45661cb0ef41Sopenharmony_ci for (Edge edge : node->use_edges()) { 45671cb0ef41Sopenharmony_ci if (NodeProperties::IsControlEdge(edge)) { 45681cb0ef41Sopenharmony_ci if (edge.from()->opcode() == IrOpcode::kIfSuccess) { 45691cb0ef41Sopenharmony_ci edge.from()->ReplaceUses(control); 45701cb0ef41Sopenharmony_ci edge.from()->Kill(); 45711cb0ef41Sopenharmony_ci } else { 45721cb0ef41Sopenharmony_ci DCHECK_NE(IrOpcode::kIfException, edge.from()->opcode()); 45731cb0ef41Sopenharmony_ci edge.UpdateTo(control); 45741cb0ef41Sopenharmony_ci } 45751cb0ef41Sopenharmony_ci } else if (NodeProperties::IsEffectEdge(edge)) { 45761cb0ef41Sopenharmony_ci edge.UpdateTo(effect); 45771cb0ef41Sopenharmony_ci } 45781cb0ef41Sopenharmony_ci } 45791cb0ef41Sopenharmony_ci 45801cb0ef41Sopenharmony_ci selector->DeferReplacement(node, value); 45811cb0ef41Sopenharmony_ci} 45821cb0ef41Sopenharmony_ci 45831cb0ef41Sopenharmony_ciNode* SimplifiedLowering::Float64Round(Node* const node) { 45841cb0ef41Sopenharmony_ci Node* const one = jsgraph()->Float64Constant(1.0); 45851cb0ef41Sopenharmony_ci Node* const one_half = jsgraph()->Float64Constant(0.5); 45861cb0ef41Sopenharmony_ci Node* const input = node->InputAt(0); 45871cb0ef41Sopenharmony_ci 45881cb0ef41Sopenharmony_ci // Round up towards Infinity, and adjust if the difference exceeds 0.5. 45891cb0ef41Sopenharmony_ci Node* result = graph()->NewNode(machine()->Float64RoundUp().placeholder(), 45901cb0ef41Sopenharmony_ci node->InputAt(0)); 45911cb0ef41Sopenharmony_ci return graph()->NewNode( 45921cb0ef41Sopenharmony_ci common()->Select(MachineRepresentation::kFloat64), 45931cb0ef41Sopenharmony_ci graph()->NewNode( 45941cb0ef41Sopenharmony_ci machine()->Float64LessThanOrEqual(), 45951cb0ef41Sopenharmony_ci graph()->NewNode(machine()->Float64Sub(), result, one_half), input), 45961cb0ef41Sopenharmony_ci result, graph()->NewNode(machine()->Float64Sub(), result, one)); 45971cb0ef41Sopenharmony_ci} 45981cb0ef41Sopenharmony_ci 45991cb0ef41Sopenharmony_ciNode* SimplifiedLowering::Float64Sign(Node* const node) { 46001cb0ef41Sopenharmony_ci Node* const minus_one = jsgraph()->Float64Constant(-1.0); 46011cb0ef41Sopenharmony_ci Node* const zero = jsgraph()->Float64Constant(0.0); 46021cb0ef41Sopenharmony_ci Node* const one = jsgraph()->Float64Constant(1.0); 46031cb0ef41Sopenharmony_ci 46041cb0ef41Sopenharmony_ci Node* const input = node->InputAt(0); 46051cb0ef41Sopenharmony_ci 46061cb0ef41Sopenharmony_ci return graph()->NewNode( 46071cb0ef41Sopenharmony_ci common()->Select(MachineRepresentation::kFloat64), 46081cb0ef41Sopenharmony_ci graph()->NewNode(machine()->Float64LessThan(), input, zero), minus_one, 46091cb0ef41Sopenharmony_ci graph()->NewNode( 46101cb0ef41Sopenharmony_ci common()->Select(MachineRepresentation::kFloat64), 46111cb0ef41Sopenharmony_ci graph()->NewNode(machine()->Float64LessThan(), zero, input), one, 46121cb0ef41Sopenharmony_ci input)); 46131cb0ef41Sopenharmony_ci} 46141cb0ef41Sopenharmony_ci 46151cb0ef41Sopenharmony_ciNode* SimplifiedLowering::Int32Abs(Node* const node) { 46161cb0ef41Sopenharmony_ci Node* const input = node->InputAt(0); 46171cb0ef41Sopenharmony_ci 46181cb0ef41Sopenharmony_ci // Generate case for absolute integer value. 46191cb0ef41Sopenharmony_ci // 46201cb0ef41Sopenharmony_ci // let sign = input >> 31 in 46211cb0ef41Sopenharmony_ci // (input ^ sign) - sign 46221cb0ef41Sopenharmony_ci 46231cb0ef41Sopenharmony_ci Node* sign = graph()->NewNode(machine()->Word32Sar(), input, 46241cb0ef41Sopenharmony_ci jsgraph()->Int32Constant(31)); 46251cb0ef41Sopenharmony_ci return graph()->NewNode(machine()->Int32Sub(), 46261cb0ef41Sopenharmony_ci graph()->NewNode(machine()->Word32Xor(), input, sign), 46271cb0ef41Sopenharmony_ci sign); 46281cb0ef41Sopenharmony_ci} 46291cb0ef41Sopenharmony_ci 46301cb0ef41Sopenharmony_ciNode* SimplifiedLowering::Int32Div(Node* const node) { 46311cb0ef41Sopenharmony_ci Int32BinopMatcher m(node); 46321cb0ef41Sopenharmony_ci Node* const zero = jsgraph()->Int32Constant(0); 46331cb0ef41Sopenharmony_ci Node* const minus_one = jsgraph()->Int32Constant(-1); 46341cb0ef41Sopenharmony_ci Node* const lhs = m.left().node(); 46351cb0ef41Sopenharmony_ci Node* const rhs = m.right().node(); 46361cb0ef41Sopenharmony_ci 46371cb0ef41Sopenharmony_ci if (m.right().Is(-1)) { 46381cb0ef41Sopenharmony_ci return graph()->NewNode(machine()->Int32Sub(), zero, lhs); 46391cb0ef41Sopenharmony_ci } else if (m.right().Is(0)) { 46401cb0ef41Sopenharmony_ci return rhs; 46411cb0ef41Sopenharmony_ci } else if (machine()->Int32DivIsSafe() || m.right().HasResolvedValue()) { 46421cb0ef41Sopenharmony_ci return graph()->NewNode(machine()->Int32Div(), lhs, rhs, graph()->start()); 46431cb0ef41Sopenharmony_ci } 46441cb0ef41Sopenharmony_ci 46451cb0ef41Sopenharmony_ci // General case for signed integer division. 46461cb0ef41Sopenharmony_ci // 46471cb0ef41Sopenharmony_ci // if 0 < rhs then 46481cb0ef41Sopenharmony_ci // lhs / rhs 46491cb0ef41Sopenharmony_ci // else 46501cb0ef41Sopenharmony_ci // if rhs < -1 then 46511cb0ef41Sopenharmony_ci // lhs / rhs 46521cb0ef41Sopenharmony_ci // else if rhs == 0 then 46531cb0ef41Sopenharmony_ci // 0 46541cb0ef41Sopenharmony_ci // else 46551cb0ef41Sopenharmony_ci // 0 - lhs 46561cb0ef41Sopenharmony_ci // 46571cb0ef41Sopenharmony_ci // Note: We do not use the Diamond helper class here, because it really hurts 46581cb0ef41Sopenharmony_ci // readability with nested diamonds. 46591cb0ef41Sopenharmony_ci const Operator* const merge_op = common()->Merge(2); 46601cb0ef41Sopenharmony_ci const Operator* const phi_op = 46611cb0ef41Sopenharmony_ci common()->Phi(MachineRepresentation::kWord32, 2); 46621cb0ef41Sopenharmony_ci 46631cb0ef41Sopenharmony_ci Node* check0 = graph()->NewNode(machine()->Int32LessThan(), zero, rhs); 46641cb0ef41Sopenharmony_ci Node* branch0 = graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, 46651cb0ef41Sopenharmony_ci graph()->start()); 46661cb0ef41Sopenharmony_ci 46671cb0ef41Sopenharmony_ci Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0); 46681cb0ef41Sopenharmony_ci Node* true0 = graph()->NewNode(machine()->Int32Div(), lhs, rhs, if_true0); 46691cb0ef41Sopenharmony_ci 46701cb0ef41Sopenharmony_ci Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0); 46711cb0ef41Sopenharmony_ci Node* false0; 46721cb0ef41Sopenharmony_ci { 46731cb0ef41Sopenharmony_ci Node* check1 = graph()->NewNode(machine()->Int32LessThan(), rhs, minus_one); 46741cb0ef41Sopenharmony_ci Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_false0); 46751cb0ef41Sopenharmony_ci 46761cb0ef41Sopenharmony_ci Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); 46771cb0ef41Sopenharmony_ci Node* true1 = graph()->NewNode(machine()->Int32Div(), lhs, rhs, if_true1); 46781cb0ef41Sopenharmony_ci 46791cb0ef41Sopenharmony_ci Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); 46801cb0ef41Sopenharmony_ci Node* false1; 46811cb0ef41Sopenharmony_ci { 46821cb0ef41Sopenharmony_ci Node* check2 = graph()->NewNode(machine()->Word32Equal(), rhs, zero); 46831cb0ef41Sopenharmony_ci Node* branch2 = graph()->NewNode(common()->Branch(), check2, if_false1); 46841cb0ef41Sopenharmony_ci 46851cb0ef41Sopenharmony_ci Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2); 46861cb0ef41Sopenharmony_ci Node* true2 = zero; 46871cb0ef41Sopenharmony_ci 46881cb0ef41Sopenharmony_ci Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2); 46891cb0ef41Sopenharmony_ci Node* false2 = graph()->NewNode(machine()->Int32Sub(), zero, lhs); 46901cb0ef41Sopenharmony_ci 46911cb0ef41Sopenharmony_ci if_false1 = graph()->NewNode(merge_op, if_true2, if_false2); 46921cb0ef41Sopenharmony_ci false1 = graph()->NewNode(phi_op, true2, false2, if_false1); 46931cb0ef41Sopenharmony_ci } 46941cb0ef41Sopenharmony_ci 46951cb0ef41Sopenharmony_ci if_false0 = graph()->NewNode(merge_op, if_true1, if_false1); 46961cb0ef41Sopenharmony_ci false0 = graph()->NewNode(phi_op, true1, false1, if_false0); 46971cb0ef41Sopenharmony_ci } 46981cb0ef41Sopenharmony_ci 46991cb0ef41Sopenharmony_ci Node* merge0 = graph()->NewNode(merge_op, if_true0, if_false0); 47001cb0ef41Sopenharmony_ci return graph()->NewNode(phi_op, true0, false0, merge0); 47011cb0ef41Sopenharmony_ci} 47021cb0ef41Sopenharmony_ci 47031cb0ef41Sopenharmony_ciNode* SimplifiedLowering::Int32Mod(Node* const node) { 47041cb0ef41Sopenharmony_ci Int32BinopMatcher m(node); 47051cb0ef41Sopenharmony_ci Node* const zero = jsgraph()->Int32Constant(0); 47061cb0ef41Sopenharmony_ci Node* const minus_one = jsgraph()->Int32Constant(-1); 47071cb0ef41Sopenharmony_ci Node* const lhs = m.left().node(); 47081cb0ef41Sopenharmony_ci Node* const rhs = m.right().node(); 47091cb0ef41Sopenharmony_ci 47101cb0ef41Sopenharmony_ci if (m.right().Is(-1) || m.right().Is(0)) { 47111cb0ef41Sopenharmony_ci return zero; 47121cb0ef41Sopenharmony_ci } else if (m.right().HasResolvedValue()) { 47131cb0ef41Sopenharmony_ci return graph()->NewNode(machine()->Int32Mod(), lhs, rhs, graph()->start()); 47141cb0ef41Sopenharmony_ci } 47151cb0ef41Sopenharmony_ci 47161cb0ef41Sopenharmony_ci // General case for signed integer modulus, with optimization for (unknown) 47171cb0ef41Sopenharmony_ci // power of 2 right hand side. 47181cb0ef41Sopenharmony_ci // 47191cb0ef41Sopenharmony_ci // if 0 < rhs then 47201cb0ef41Sopenharmony_ci // msk = rhs - 1 47211cb0ef41Sopenharmony_ci // if rhs & msk != 0 then 47221cb0ef41Sopenharmony_ci // lhs % rhs 47231cb0ef41Sopenharmony_ci // else 47241cb0ef41Sopenharmony_ci // if lhs < 0 then 47251cb0ef41Sopenharmony_ci // -(-lhs & msk) 47261cb0ef41Sopenharmony_ci // else 47271cb0ef41Sopenharmony_ci // lhs & msk 47281cb0ef41Sopenharmony_ci // else 47291cb0ef41Sopenharmony_ci // if rhs < -1 then 47301cb0ef41Sopenharmony_ci // lhs % rhs 47311cb0ef41Sopenharmony_ci // else 47321cb0ef41Sopenharmony_ci // zero 47331cb0ef41Sopenharmony_ci // 47341cb0ef41Sopenharmony_ci // Note: We do not use the Diamond helper class here, because it really hurts 47351cb0ef41Sopenharmony_ci // readability with nested diamonds. 47361cb0ef41Sopenharmony_ci const Operator* const merge_op = common()->Merge(2); 47371cb0ef41Sopenharmony_ci const Operator* const phi_op = 47381cb0ef41Sopenharmony_ci common()->Phi(MachineRepresentation::kWord32, 2); 47391cb0ef41Sopenharmony_ci 47401cb0ef41Sopenharmony_ci Node* check0 = graph()->NewNode(machine()->Int32LessThan(), zero, rhs); 47411cb0ef41Sopenharmony_ci Node* branch0 = graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, 47421cb0ef41Sopenharmony_ci graph()->start()); 47431cb0ef41Sopenharmony_ci 47441cb0ef41Sopenharmony_ci Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0); 47451cb0ef41Sopenharmony_ci Node* true0; 47461cb0ef41Sopenharmony_ci { 47471cb0ef41Sopenharmony_ci Node* msk = graph()->NewNode(machine()->Int32Add(), rhs, minus_one); 47481cb0ef41Sopenharmony_ci 47491cb0ef41Sopenharmony_ci Node* check1 = graph()->NewNode(machine()->Word32And(), rhs, msk); 47501cb0ef41Sopenharmony_ci Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_true0); 47511cb0ef41Sopenharmony_ci 47521cb0ef41Sopenharmony_ci Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); 47531cb0ef41Sopenharmony_ci Node* true1 = graph()->NewNode(machine()->Int32Mod(), lhs, rhs, if_true1); 47541cb0ef41Sopenharmony_ci 47551cb0ef41Sopenharmony_ci Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); 47561cb0ef41Sopenharmony_ci Node* false1; 47571cb0ef41Sopenharmony_ci { 47581cb0ef41Sopenharmony_ci Node* check2 = graph()->NewNode(machine()->Int32LessThan(), lhs, zero); 47591cb0ef41Sopenharmony_ci Node* branch2 = graph()->NewNode(common()->Branch(BranchHint::kFalse), 47601cb0ef41Sopenharmony_ci check2, if_false1); 47611cb0ef41Sopenharmony_ci 47621cb0ef41Sopenharmony_ci Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2); 47631cb0ef41Sopenharmony_ci Node* true2 = graph()->NewNode( 47641cb0ef41Sopenharmony_ci machine()->Int32Sub(), zero, 47651cb0ef41Sopenharmony_ci graph()->NewNode(machine()->Word32And(), 47661cb0ef41Sopenharmony_ci graph()->NewNode(machine()->Int32Sub(), zero, lhs), 47671cb0ef41Sopenharmony_ci msk)); 47681cb0ef41Sopenharmony_ci 47691cb0ef41Sopenharmony_ci Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2); 47701cb0ef41Sopenharmony_ci Node* false2 = graph()->NewNode(machine()->Word32And(), lhs, msk); 47711cb0ef41Sopenharmony_ci 47721cb0ef41Sopenharmony_ci if_false1 = graph()->NewNode(merge_op, if_true2, if_false2); 47731cb0ef41Sopenharmony_ci false1 = graph()->NewNode(phi_op, true2, false2, if_false1); 47741cb0ef41Sopenharmony_ci } 47751cb0ef41Sopenharmony_ci 47761cb0ef41Sopenharmony_ci if_true0 = graph()->NewNode(merge_op, if_true1, if_false1); 47771cb0ef41Sopenharmony_ci true0 = graph()->NewNode(phi_op, true1, false1, if_true0); 47781cb0ef41Sopenharmony_ci } 47791cb0ef41Sopenharmony_ci 47801cb0ef41Sopenharmony_ci Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0); 47811cb0ef41Sopenharmony_ci Node* false0; 47821cb0ef41Sopenharmony_ci { 47831cb0ef41Sopenharmony_ci Node* check1 = graph()->NewNode(machine()->Int32LessThan(), rhs, minus_one); 47841cb0ef41Sopenharmony_ci Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kTrue), 47851cb0ef41Sopenharmony_ci check1, if_false0); 47861cb0ef41Sopenharmony_ci 47871cb0ef41Sopenharmony_ci Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); 47881cb0ef41Sopenharmony_ci Node* true1 = graph()->NewNode(machine()->Int32Mod(), lhs, rhs, if_true1); 47891cb0ef41Sopenharmony_ci 47901cb0ef41Sopenharmony_ci Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); 47911cb0ef41Sopenharmony_ci Node* false1 = zero; 47921cb0ef41Sopenharmony_ci 47931cb0ef41Sopenharmony_ci if_false0 = graph()->NewNode(merge_op, if_true1, if_false1); 47941cb0ef41Sopenharmony_ci false0 = graph()->NewNode(phi_op, true1, false1, if_false0); 47951cb0ef41Sopenharmony_ci } 47961cb0ef41Sopenharmony_ci 47971cb0ef41Sopenharmony_ci Node* merge0 = graph()->NewNode(merge_op, if_true0, if_false0); 47981cb0ef41Sopenharmony_ci return graph()->NewNode(phi_op, true0, false0, merge0); 47991cb0ef41Sopenharmony_ci} 48001cb0ef41Sopenharmony_ci 48011cb0ef41Sopenharmony_ciNode* SimplifiedLowering::Int32Sign(Node* const node) { 48021cb0ef41Sopenharmony_ci Node* const minus_one = jsgraph()->Int32Constant(-1); 48031cb0ef41Sopenharmony_ci Node* const zero = jsgraph()->Int32Constant(0); 48041cb0ef41Sopenharmony_ci Node* const one = jsgraph()->Int32Constant(1); 48051cb0ef41Sopenharmony_ci 48061cb0ef41Sopenharmony_ci Node* const input = node->InputAt(0); 48071cb0ef41Sopenharmony_ci 48081cb0ef41Sopenharmony_ci return graph()->NewNode( 48091cb0ef41Sopenharmony_ci common()->Select(MachineRepresentation::kWord32), 48101cb0ef41Sopenharmony_ci graph()->NewNode(machine()->Int32LessThan(), input, zero), minus_one, 48111cb0ef41Sopenharmony_ci graph()->NewNode( 48121cb0ef41Sopenharmony_ci common()->Select(MachineRepresentation::kWord32), 48131cb0ef41Sopenharmony_ci graph()->NewNode(machine()->Int32LessThan(), zero, input), one, 48141cb0ef41Sopenharmony_ci zero)); 48151cb0ef41Sopenharmony_ci} 48161cb0ef41Sopenharmony_ci 48171cb0ef41Sopenharmony_ciNode* SimplifiedLowering::Uint32Div(Node* const node) { 48181cb0ef41Sopenharmony_ci Uint32BinopMatcher m(node); 48191cb0ef41Sopenharmony_ci Node* const zero = jsgraph()->Uint32Constant(0); 48201cb0ef41Sopenharmony_ci Node* const lhs = m.left().node(); 48211cb0ef41Sopenharmony_ci Node* const rhs = m.right().node(); 48221cb0ef41Sopenharmony_ci 48231cb0ef41Sopenharmony_ci if (m.right().Is(0)) { 48241cb0ef41Sopenharmony_ci return zero; 48251cb0ef41Sopenharmony_ci } else if (machine()->Uint32DivIsSafe() || m.right().HasResolvedValue()) { 48261cb0ef41Sopenharmony_ci return graph()->NewNode(machine()->Uint32Div(), lhs, rhs, graph()->start()); 48271cb0ef41Sopenharmony_ci } 48281cb0ef41Sopenharmony_ci 48291cb0ef41Sopenharmony_ci Node* check = graph()->NewNode(machine()->Word32Equal(), rhs, zero); 48301cb0ef41Sopenharmony_ci Diamond d(graph(), common(), check, BranchHint::kFalse); 48311cb0ef41Sopenharmony_ci Node* div = graph()->NewNode(machine()->Uint32Div(), lhs, rhs, d.if_false); 48321cb0ef41Sopenharmony_ci return d.Phi(MachineRepresentation::kWord32, zero, div); 48331cb0ef41Sopenharmony_ci} 48341cb0ef41Sopenharmony_ci 48351cb0ef41Sopenharmony_ciNode* SimplifiedLowering::Uint32Mod(Node* const node) { 48361cb0ef41Sopenharmony_ci Uint32BinopMatcher m(node); 48371cb0ef41Sopenharmony_ci Node* const minus_one = jsgraph()->Int32Constant(-1); 48381cb0ef41Sopenharmony_ci Node* const zero = jsgraph()->Uint32Constant(0); 48391cb0ef41Sopenharmony_ci Node* const lhs = m.left().node(); 48401cb0ef41Sopenharmony_ci Node* const rhs = m.right().node(); 48411cb0ef41Sopenharmony_ci 48421cb0ef41Sopenharmony_ci if (m.right().Is(0)) { 48431cb0ef41Sopenharmony_ci return zero; 48441cb0ef41Sopenharmony_ci } else if (m.right().HasResolvedValue()) { 48451cb0ef41Sopenharmony_ci return graph()->NewNode(machine()->Uint32Mod(), lhs, rhs, graph()->start()); 48461cb0ef41Sopenharmony_ci } 48471cb0ef41Sopenharmony_ci 48481cb0ef41Sopenharmony_ci // General case for unsigned integer modulus, with optimization for (unknown) 48491cb0ef41Sopenharmony_ci // power of 2 right hand side. 48501cb0ef41Sopenharmony_ci // 48511cb0ef41Sopenharmony_ci // if rhs == 0 then 48521cb0ef41Sopenharmony_ci // zero 48531cb0ef41Sopenharmony_ci // else 48541cb0ef41Sopenharmony_ci // msk = rhs - 1 48551cb0ef41Sopenharmony_ci // if rhs & msk != 0 then 48561cb0ef41Sopenharmony_ci // lhs % rhs 48571cb0ef41Sopenharmony_ci // else 48581cb0ef41Sopenharmony_ci // lhs & msk 48591cb0ef41Sopenharmony_ci // 48601cb0ef41Sopenharmony_ci // Note: We do not use the Diamond helper class here, because it really hurts 48611cb0ef41Sopenharmony_ci // readability with nested diamonds. 48621cb0ef41Sopenharmony_ci const Operator* const merge_op = common()->Merge(2); 48631cb0ef41Sopenharmony_ci const Operator* const phi_op = 48641cb0ef41Sopenharmony_ci common()->Phi(MachineRepresentation::kWord32, 2); 48651cb0ef41Sopenharmony_ci 48661cb0ef41Sopenharmony_ci Node* check0 = graph()->NewNode(machine()->Word32Equal(), rhs, zero); 48671cb0ef41Sopenharmony_ci Node* branch0 = graph()->NewNode(common()->Branch(BranchHint::kFalse), check0, 48681cb0ef41Sopenharmony_ci graph()->start()); 48691cb0ef41Sopenharmony_ci 48701cb0ef41Sopenharmony_ci Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0); 48711cb0ef41Sopenharmony_ci Node* true0 = zero; 48721cb0ef41Sopenharmony_ci 48731cb0ef41Sopenharmony_ci Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0); 48741cb0ef41Sopenharmony_ci Node* false0; 48751cb0ef41Sopenharmony_ci { 48761cb0ef41Sopenharmony_ci Node* msk = graph()->NewNode(machine()->Int32Add(), rhs, minus_one); 48771cb0ef41Sopenharmony_ci 48781cb0ef41Sopenharmony_ci Node* check1 = graph()->NewNode(machine()->Word32And(), rhs, msk); 48791cb0ef41Sopenharmony_ci Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_false0); 48801cb0ef41Sopenharmony_ci 48811cb0ef41Sopenharmony_ci Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); 48821cb0ef41Sopenharmony_ci Node* true1 = graph()->NewNode(machine()->Uint32Mod(), lhs, rhs, if_true1); 48831cb0ef41Sopenharmony_ci 48841cb0ef41Sopenharmony_ci Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); 48851cb0ef41Sopenharmony_ci Node* false1 = graph()->NewNode(machine()->Word32And(), lhs, msk); 48861cb0ef41Sopenharmony_ci 48871cb0ef41Sopenharmony_ci if_false0 = graph()->NewNode(merge_op, if_true1, if_false1); 48881cb0ef41Sopenharmony_ci false0 = graph()->NewNode(phi_op, true1, false1, if_false0); 48891cb0ef41Sopenharmony_ci } 48901cb0ef41Sopenharmony_ci 48911cb0ef41Sopenharmony_ci Node* merge0 = graph()->NewNode(merge_op, if_true0, if_false0); 48921cb0ef41Sopenharmony_ci return graph()->NewNode(phi_op, true0, false0, merge0); 48931cb0ef41Sopenharmony_ci} 48941cb0ef41Sopenharmony_ci 48951cb0ef41Sopenharmony_civoid SimplifiedLowering::DoMax(Node* node, Operator const* op, 48961cb0ef41Sopenharmony_ci MachineRepresentation rep) { 48971cb0ef41Sopenharmony_ci Node* const lhs = node->InputAt(0); 48981cb0ef41Sopenharmony_ci Node* const rhs = node->InputAt(1); 48991cb0ef41Sopenharmony_ci 49001cb0ef41Sopenharmony_ci node->ReplaceInput(0, graph()->NewNode(op, lhs, rhs)); 49011cb0ef41Sopenharmony_ci DCHECK_EQ(rhs, node->InputAt(1)); 49021cb0ef41Sopenharmony_ci node->AppendInput(graph()->zone(), lhs); 49031cb0ef41Sopenharmony_ci ChangeOp(node, common()->Select(rep)); 49041cb0ef41Sopenharmony_ci} 49051cb0ef41Sopenharmony_ci 49061cb0ef41Sopenharmony_civoid SimplifiedLowering::DoMin(Node* node, Operator const* op, 49071cb0ef41Sopenharmony_ci MachineRepresentation rep) { 49081cb0ef41Sopenharmony_ci Node* const lhs = node->InputAt(0); 49091cb0ef41Sopenharmony_ci Node* const rhs = node->InputAt(1); 49101cb0ef41Sopenharmony_ci 49111cb0ef41Sopenharmony_ci node->InsertInput(graph()->zone(), 0, graph()->NewNode(op, lhs, rhs)); 49121cb0ef41Sopenharmony_ci DCHECK_EQ(lhs, node->InputAt(1)); 49131cb0ef41Sopenharmony_ci DCHECK_EQ(rhs, node->InputAt(2)); 49141cb0ef41Sopenharmony_ci ChangeOp(node, common()->Select(rep)); 49151cb0ef41Sopenharmony_ci} 49161cb0ef41Sopenharmony_ci 49171cb0ef41Sopenharmony_civoid SimplifiedLowering::DoIntegral32ToBit(Node* node) { 49181cb0ef41Sopenharmony_ci Node* const input = node->InputAt(0); 49191cb0ef41Sopenharmony_ci Node* const zero = jsgraph()->Int32Constant(0); 49201cb0ef41Sopenharmony_ci Operator const* const op = machine()->Word32Equal(); 49211cb0ef41Sopenharmony_ci 49221cb0ef41Sopenharmony_ci node->ReplaceInput(0, graph()->NewNode(op, input, zero)); 49231cb0ef41Sopenharmony_ci node->AppendInput(graph()->zone(), zero); 49241cb0ef41Sopenharmony_ci ChangeOp(node, op); 49251cb0ef41Sopenharmony_ci} 49261cb0ef41Sopenharmony_ci 49271cb0ef41Sopenharmony_civoid SimplifiedLowering::DoOrderedNumberToBit(Node* node) { 49281cb0ef41Sopenharmony_ci Node* const input = node->InputAt(0); 49291cb0ef41Sopenharmony_ci 49301cb0ef41Sopenharmony_ci node->ReplaceInput(0, graph()->NewNode(machine()->Float64Equal(), input, 49311cb0ef41Sopenharmony_ci jsgraph()->Float64Constant(0.0))); 49321cb0ef41Sopenharmony_ci node->AppendInput(graph()->zone(), jsgraph()->Int32Constant(0)); 49331cb0ef41Sopenharmony_ci ChangeOp(node, machine()->Word32Equal()); 49341cb0ef41Sopenharmony_ci} 49351cb0ef41Sopenharmony_ci 49361cb0ef41Sopenharmony_civoid SimplifiedLowering::DoNumberToBit(Node* node) { 49371cb0ef41Sopenharmony_ci Node* const input = node->InputAt(0); 49381cb0ef41Sopenharmony_ci 49391cb0ef41Sopenharmony_ci node->ReplaceInput(0, jsgraph()->Float64Constant(0.0)); 49401cb0ef41Sopenharmony_ci node->AppendInput(graph()->zone(), 49411cb0ef41Sopenharmony_ci graph()->NewNode(machine()->Float64Abs(), input)); 49421cb0ef41Sopenharmony_ci ChangeOp(node, machine()->Float64LessThan()); 49431cb0ef41Sopenharmony_ci} 49441cb0ef41Sopenharmony_ci 49451cb0ef41Sopenharmony_civoid SimplifiedLowering::DoIntegerToUint8Clamped(Node* node) { 49461cb0ef41Sopenharmony_ci Node* const input = node->InputAt(0); 49471cb0ef41Sopenharmony_ci Node* const min = jsgraph()->Float64Constant(0.0); 49481cb0ef41Sopenharmony_ci Node* const max = jsgraph()->Float64Constant(255.0); 49491cb0ef41Sopenharmony_ci 49501cb0ef41Sopenharmony_ci node->ReplaceInput( 49511cb0ef41Sopenharmony_ci 0, graph()->NewNode(machine()->Float64LessThan(), min, input)); 49521cb0ef41Sopenharmony_ci node->AppendInput( 49531cb0ef41Sopenharmony_ci graph()->zone(), 49541cb0ef41Sopenharmony_ci graph()->NewNode( 49551cb0ef41Sopenharmony_ci common()->Select(MachineRepresentation::kFloat64), 49561cb0ef41Sopenharmony_ci graph()->NewNode(machine()->Float64LessThan(), input, max), input, 49571cb0ef41Sopenharmony_ci max)); 49581cb0ef41Sopenharmony_ci node->AppendInput(graph()->zone(), min); 49591cb0ef41Sopenharmony_ci ChangeOp(node, common()->Select(MachineRepresentation::kFloat64)); 49601cb0ef41Sopenharmony_ci} 49611cb0ef41Sopenharmony_ci 49621cb0ef41Sopenharmony_civoid SimplifiedLowering::DoNumberToUint8Clamped(Node* node) { 49631cb0ef41Sopenharmony_ci Node* const input = node->InputAt(0); 49641cb0ef41Sopenharmony_ci Node* const min = jsgraph()->Float64Constant(0.0); 49651cb0ef41Sopenharmony_ci Node* const max = jsgraph()->Float64Constant(255.0); 49661cb0ef41Sopenharmony_ci 49671cb0ef41Sopenharmony_ci node->ReplaceInput( 49681cb0ef41Sopenharmony_ci 0, graph()->NewNode( 49691cb0ef41Sopenharmony_ci common()->Select(MachineRepresentation::kFloat64), 49701cb0ef41Sopenharmony_ci graph()->NewNode(machine()->Float64LessThan(), min, input), 49711cb0ef41Sopenharmony_ci graph()->NewNode( 49721cb0ef41Sopenharmony_ci common()->Select(MachineRepresentation::kFloat64), 49731cb0ef41Sopenharmony_ci graph()->NewNode(machine()->Float64LessThan(), input, max), 49741cb0ef41Sopenharmony_ci input, max), 49751cb0ef41Sopenharmony_ci min)); 49761cb0ef41Sopenharmony_ci ChangeOp(node, machine()->Float64RoundTiesEven().placeholder()); 49771cb0ef41Sopenharmony_ci} 49781cb0ef41Sopenharmony_ci 49791cb0ef41Sopenharmony_civoid SimplifiedLowering::DoSigned32ToUint8Clamped(Node* node) { 49801cb0ef41Sopenharmony_ci Node* const input = node->InputAt(0); 49811cb0ef41Sopenharmony_ci Node* const min = jsgraph()->Int32Constant(0); 49821cb0ef41Sopenharmony_ci Node* const max = jsgraph()->Int32Constant(255); 49831cb0ef41Sopenharmony_ci 49841cb0ef41Sopenharmony_ci node->ReplaceInput( 49851cb0ef41Sopenharmony_ci 0, graph()->NewNode(machine()->Int32LessThanOrEqual(), input, max)); 49861cb0ef41Sopenharmony_ci node->AppendInput( 49871cb0ef41Sopenharmony_ci graph()->zone(), 49881cb0ef41Sopenharmony_ci graph()->NewNode(common()->Select(MachineRepresentation::kWord32), 49891cb0ef41Sopenharmony_ci graph()->NewNode(machine()->Int32LessThan(), input, min), 49901cb0ef41Sopenharmony_ci min, input)); 49911cb0ef41Sopenharmony_ci node->AppendInput(graph()->zone(), max); 49921cb0ef41Sopenharmony_ci ChangeOp(node, common()->Select(MachineRepresentation::kWord32)); 49931cb0ef41Sopenharmony_ci} 49941cb0ef41Sopenharmony_ci 49951cb0ef41Sopenharmony_civoid SimplifiedLowering::DoUnsigned32ToUint8Clamped(Node* node) { 49961cb0ef41Sopenharmony_ci Node* const input = node->InputAt(0); 49971cb0ef41Sopenharmony_ci Node* const max = jsgraph()->Uint32Constant(255u); 49981cb0ef41Sopenharmony_ci 49991cb0ef41Sopenharmony_ci node->ReplaceInput( 50001cb0ef41Sopenharmony_ci 0, graph()->NewNode(machine()->Uint32LessThanOrEqual(), input, max)); 50011cb0ef41Sopenharmony_ci node->AppendInput(graph()->zone(), input); 50021cb0ef41Sopenharmony_ci node->AppendInput(graph()->zone(), max); 50031cb0ef41Sopenharmony_ci ChangeOp(node, common()->Select(MachineRepresentation::kWord32)); 50041cb0ef41Sopenharmony_ci} 50051cb0ef41Sopenharmony_ci 50061cb0ef41Sopenharmony_ciNode* SimplifiedLowering::ToNumberCode() { 50071cb0ef41Sopenharmony_ci if (!to_number_code_.is_set()) { 50081cb0ef41Sopenharmony_ci Callable callable = Builtins::CallableFor(isolate(), Builtin::kToNumber); 50091cb0ef41Sopenharmony_ci to_number_code_.set(jsgraph()->HeapConstant(callable.code())); 50101cb0ef41Sopenharmony_ci } 50111cb0ef41Sopenharmony_ci return to_number_code_.get(); 50121cb0ef41Sopenharmony_ci} 50131cb0ef41Sopenharmony_ci 50141cb0ef41Sopenharmony_ciNode* SimplifiedLowering::ToNumberConvertBigIntCode() { 50151cb0ef41Sopenharmony_ci if (!to_number_convert_big_int_code_.is_set()) { 50161cb0ef41Sopenharmony_ci Callable callable = 50171cb0ef41Sopenharmony_ci Builtins::CallableFor(isolate(), Builtin::kToNumberConvertBigInt); 50181cb0ef41Sopenharmony_ci to_number_convert_big_int_code_.set( 50191cb0ef41Sopenharmony_ci jsgraph()->HeapConstant(callable.code())); 50201cb0ef41Sopenharmony_ci } 50211cb0ef41Sopenharmony_ci return to_number_convert_big_int_code_.get(); 50221cb0ef41Sopenharmony_ci} 50231cb0ef41Sopenharmony_ci 50241cb0ef41Sopenharmony_ciNode* SimplifiedLowering::ToNumericCode() { 50251cb0ef41Sopenharmony_ci if (!to_numeric_code_.is_set()) { 50261cb0ef41Sopenharmony_ci Callable callable = Builtins::CallableFor(isolate(), Builtin::kToNumeric); 50271cb0ef41Sopenharmony_ci to_numeric_code_.set(jsgraph()->HeapConstant(callable.code())); 50281cb0ef41Sopenharmony_ci } 50291cb0ef41Sopenharmony_ci return to_numeric_code_.get(); 50301cb0ef41Sopenharmony_ci} 50311cb0ef41Sopenharmony_ci 50321cb0ef41Sopenharmony_ciOperator const* SimplifiedLowering::ToNumberOperator() { 50331cb0ef41Sopenharmony_ci if (!to_number_operator_.is_set()) { 50341cb0ef41Sopenharmony_ci Callable callable = Builtins::CallableFor(isolate(), Builtin::kToNumber); 50351cb0ef41Sopenharmony_ci CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState; 50361cb0ef41Sopenharmony_ci auto call_descriptor = Linkage::GetStubCallDescriptor( 50371cb0ef41Sopenharmony_ci graph()->zone(), callable.descriptor(), 50381cb0ef41Sopenharmony_ci callable.descriptor().GetStackParameterCount(), flags, 50391cb0ef41Sopenharmony_ci Operator::kNoProperties); 50401cb0ef41Sopenharmony_ci to_number_operator_.set(common()->Call(call_descriptor)); 50411cb0ef41Sopenharmony_ci } 50421cb0ef41Sopenharmony_ci return to_number_operator_.get(); 50431cb0ef41Sopenharmony_ci} 50441cb0ef41Sopenharmony_ci 50451cb0ef41Sopenharmony_ciOperator const* SimplifiedLowering::ToNumberConvertBigIntOperator() { 50461cb0ef41Sopenharmony_ci if (!to_number_convert_big_int_operator_.is_set()) { 50471cb0ef41Sopenharmony_ci Callable callable = 50481cb0ef41Sopenharmony_ci Builtins::CallableFor(isolate(), Builtin::kToNumberConvertBigInt); 50491cb0ef41Sopenharmony_ci CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState; 50501cb0ef41Sopenharmony_ci auto call_descriptor = Linkage::GetStubCallDescriptor( 50511cb0ef41Sopenharmony_ci graph()->zone(), callable.descriptor(), 50521cb0ef41Sopenharmony_ci callable.descriptor().GetStackParameterCount(), flags, 50531cb0ef41Sopenharmony_ci Operator::kNoProperties); 50541cb0ef41Sopenharmony_ci to_number_convert_big_int_operator_.set(common()->Call(call_descriptor)); 50551cb0ef41Sopenharmony_ci } 50561cb0ef41Sopenharmony_ci return to_number_convert_big_int_operator_.get(); 50571cb0ef41Sopenharmony_ci} 50581cb0ef41Sopenharmony_ci 50591cb0ef41Sopenharmony_ciOperator const* SimplifiedLowering::ToNumericOperator() { 50601cb0ef41Sopenharmony_ci if (!to_numeric_operator_.is_set()) { 50611cb0ef41Sopenharmony_ci Callable callable = Builtins::CallableFor(isolate(), Builtin::kToNumeric); 50621cb0ef41Sopenharmony_ci CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState; 50631cb0ef41Sopenharmony_ci auto call_descriptor = Linkage::GetStubCallDescriptor( 50641cb0ef41Sopenharmony_ci graph()->zone(), callable.descriptor(), 50651cb0ef41Sopenharmony_ci callable.descriptor().GetStackParameterCount(), flags, 50661cb0ef41Sopenharmony_ci Operator::kNoProperties); 50671cb0ef41Sopenharmony_ci to_numeric_operator_.set(common()->Call(call_descriptor)); 50681cb0ef41Sopenharmony_ci } 50691cb0ef41Sopenharmony_ci return to_numeric_operator_.get(); 50701cb0ef41Sopenharmony_ci} 50711cb0ef41Sopenharmony_ci 50721cb0ef41Sopenharmony_civoid SimplifiedLowering::ChangeOp(Node* node, const Operator* new_op) { 50731cb0ef41Sopenharmony_ci compiler::NodeProperties::ChangeOp(node, new_op); 50741cb0ef41Sopenharmony_ci 50751cb0ef41Sopenharmony_ci if (V8_UNLIKELY(observe_node_manager_ != nullptr)) 50761cb0ef41Sopenharmony_ci observe_node_manager_->OnNodeChanged(kSimplifiedLoweringReducerName, node, 50771cb0ef41Sopenharmony_ci node); 50781cb0ef41Sopenharmony_ci} 50791cb0ef41Sopenharmony_ci 50801cb0ef41Sopenharmony_ci#undef TRACE 50811cb0ef41Sopenharmony_ci 50821cb0ef41Sopenharmony_ci} // namespace compiler 50831cb0ef41Sopenharmony_ci} // namespace internal 50841cb0ef41Sopenharmony_ci} // namespace v8 5085