26 switch (node->opcode()) {
27 case IrOpcode::kCheckBigInt:
28 case IrOpcode::kCheckedBigIntToBigInt64:
29 case IrOpcode::kCheckBounds:
30 case IrOpcode::kCheckClosure:
31 case IrOpcode::kCheckEqualsInternalizedString:
32 case IrOpcode::kCheckEqualsSymbol:
33 case IrOpcode::kCheckFloat64Hole:
34 case IrOpcode::kCheckHeapObject:
35 case IrOpcode::kCheckIf:
36 case IrOpcode::kCheckInternalizedString:
37 case IrOpcode::kCheckNotTaggedHole:
38 case IrOpcode::kCheckNumber:
39 case IrOpcode::kCheckNumberFitsInt32:
40 case IrOpcode::kCheckReceiver:
41 case IrOpcode::kCheckReceiverOrNullOrUndefined:
42 case IrOpcode::kCheckSmi:
43 case IrOpcode::kCheckString:
44 case IrOpcode::kCheckStringOrStringWrapper:
45 case IrOpcode::kCheckSymbol:
48 case IrOpcode::kStringCharCodeAt:
49 case IrOpcode::kStringCodePointAt:
50 case IrOpcode::kStringFromCodePointAt:
51 case IrOpcode::kStringSubstring:
52#define SIMPLIFIED_OP(Opcode) case IrOpcode::k##Opcode:
57 case IrOpcode::kSpeculativeNumberEqual:
58 case IrOpcode::kSpeculativeNumberLessThan:
59 case IrOpcode::kSpeculativeNumberLessThanOrEqual:
61 case IrOpcode::kSpeculativeNumberAdd:
62 case IrOpcode::kSpeculativeNumberSubtract:
63 case IrOpcode::kSpeculativeAdditiveSafeIntegerAdd:
64 case IrOpcode::kSpeculativeAdditiveSafeIntegerSubtract:
65 case IrOpcode::kSpeculativeSmallIntegerAdd:
66 case IrOpcode::kSpeculativeSmallIntegerSubtract:
67 case IrOpcode::kSpeculativeToNumber:
69 case IrOpcode::kEffectPhi:
73 case IrOpcode::kStart:
97 Check* this_head = this->head_;
98 Check* that_head = that->head_;
99 while (this_head != that_head) {
100 if (this_head->
node != that_head->
node)
return false;
101 this_head = this_head->
next;
102 that_head = that_head->
next;
114 Check* that_head = that->head_;
115 size_t that_size = that->size_;
116 while (that_size >
size_) {
117 that_head = that_head->
next;
120 while (
size_ > that_size) {
127 while (head_ != that_head) {
132 that_head = that_head->
next;
152 static Subsumption
None() {
return Subsumption(Kind::kNone,
nullptr); }
153 static Subsumption Implicit() {
154 return Subsumption(Kind::kImplicit,
nullptr);
156 static Subsumption WithConversion(
const Operator* conversion_op) {
157 return Subsumption(Kind::kWithConversion, conversion_op);
160 bool IsNone()
const {
return kind_ == Kind::kNone; }
161 bool IsImplicit()
const {
return kind_ == Kind::kImplicit; }
162 bool IsWithConversion()
const {
return kind_ == Kind::kWithConversion; }
163 const Operator* conversion_operator()
const {
164 DCHECK(IsWithConversion());
169 Subsumption(Kind
kind,
const Operator* conversion_op)
179Subsumption CheckSubsumes(Node
const* a, Node
const* b,
180 MachineOperatorBuilder* machine) {
181 Subsumption subsumption = Subsumption::Implicit();
182 if (a->op() != b->op()) {
183 if (a->opcode() == IrOpcode::kCheckInternalizedString &&
184 b->opcode() == IrOpcode::kCheckString) {
186 }
else if (a->opcode() == IrOpcode::kCheckString &&
187 b->opcode() == IrOpcode::kCheckStringOrStringWrapper) {
189 }
else if (a->opcode() == IrOpcode::kCheckInternalizedString &&
190 b->opcode() == IrOpcode::kCheckStringOrStringWrapper) {
192 }
else if (a->opcode() == IrOpcode::kCheckSmi &&
193 b->opcode() == IrOpcode::kCheckNumber) {
195 }
else if (a->opcode() == IrOpcode::kCheckSmi &&
196 b->opcode() == IrOpcode::kCheckNumberFitsInt32) {
198 }
else if (a->opcode() == IrOpcode::kCheckNumberFitsInt32 &&
199 b->opcode() == IrOpcode::kCheckNumber) {
201 }
else if (a->opcode() == IrOpcode::kCheckedTaggedSignedToInt32 &&
202 b->opcode() == IrOpcode::kCheckedTaggedToInt32) {
204 }
else if (a->opcode() == IrOpcode::kCheckedTaggedSignedToInt32 &&
205 b->opcode() == IrOpcode::kCheckedTaggedToArrayIndex) {
208 if (machine->Is64()) {
211 Subsumption::WithConversion(machine->ChangeInt32ToInt64());
213 }
else if (a->opcode() == IrOpcode::kCheckedTaggedToInt32 &&
214 b->opcode() == IrOpcode::kCheckedTaggedToArrayIndex) {
216 if (machine->Is64()) {
219 Subsumption::WithConversion(machine->ChangeInt32ToInt64());
221 }
else if (a->opcode() == IrOpcode::kCheckReceiver &&
222 b->opcode() == IrOpcode::kCheckReceiverOrNullOrUndefined) {
224 }
else if (a->opcode() != b->opcode()) {
225 return Subsumption::None();
227 switch (a->opcode()) {
228 case IrOpcode::kCheckBounds:
229 case IrOpcode::kCheckSmi:
230 case IrOpcode::kCheckString:
231 case IrOpcode::kCheckStringOrStringWrapper:
232 case IrOpcode::kCheckNumber:
233 case IrOpcode::kCheckNumberFitsInt32:
234 case IrOpcode::kCheckBigInt:
235 case IrOpcode::kCheckedBigIntToBigInt64:
237 case IrOpcode::kCheckedInt32ToTaggedSigned:
238 case IrOpcode::kCheckedInt64ToInt32:
239 case IrOpcode::kCheckedInt64ToTaggedSigned:
240 case IrOpcode::kCheckedTaggedSignedToInt32:
241 case IrOpcode::kCheckedTaggedToTaggedPointer:
242 case IrOpcode::kCheckedTaggedToTaggedSigned:
243 case IrOpcode::kCheckedTaggedToArrayIndex:
244 case IrOpcode::kCheckedUint32Bounds:
245 case IrOpcode::kCheckedUint32ToInt32:
246 case IrOpcode::kCheckedUint32ToTaggedSigned:
247 case IrOpcode::kCheckedUint64Bounds:
248 case IrOpcode::kCheckedUint64ToInt32:
249 case IrOpcode::kCheckedUint64ToTaggedSigned:
251 case IrOpcode::kCheckedFloat64ToInt32:
252 case IrOpcode::kCheckedFloat64ToAdditiveSafeInteger:
253 case IrOpcode::kCheckedFloat64ToInt64:
254 case IrOpcode::kCheckedTaggedToInt32:
255 case IrOpcode::kCheckedTaggedToAdditiveSafeInteger:
256 case IrOpcode::kCheckedTaggedToInt64: {
257 const CheckMinusZeroParameters& ap =
259 const CheckMinusZeroParameters& bp =
261 if (ap.mode() != bp.mode()) {
262 return Subsumption::None();
266 case IrOpcode::kCheckedTaggedToFloat64:
267 case IrOpcode::kCheckedTruncateTaggedToWord32: {
268 CheckTaggedInputParameters
const& ap =
270 CheckTaggedInputParameters
const& bp =
274 if (ap.mode() != bp.mode() &&
276 return Subsumption::None();
282 return Subsumption::None();
286 for (
int i = a->op()->ValueInputCount(); --
i >= 0;) {
287 if (a->InputAt(
i) != b->InputAt(
i))
return Subsumption::None();
292bool TypeSubsumes(Node* node, Node* replacement) {
300 return replacement_type.Is(node_type);
307 for (
Check const* check = head_; check !=
nullptr; check = check->
next) {
308 Subsumption subsumption =
309 CheckSubsumes(check->node, node,
jsgraph->machine());
310 if (!subsumption.IsNone() && TypeSubsumes(node, check->node)) {
311 DCHECK(!check->node->IsDead());
313 if (subsumption.IsWithConversion()) {
314 result =
jsgraph->graph()->NewNode(subsumption.conversion_operator(),
325 for (
Check const* check = head_; check !=
nullptr; check = check->
next) {
326 if (check->node->opcode() == IrOpcode::kCheckBounds &&
327 check->node->InputAt(0) == node && TypeSubsumes(node, check->node) &&
338 size_t const id = node->id();
339 if (
id < info_for_node_.size())
return info_for_node_[id];
345 size_t const id = node->id();
346 if (
id >= info_for_node_.size()) info_for_node_.resize(
id + 1,
nullptr);
347 info_for_node_[id] = checks;
355 if (checks ==
nullptr)
return NoChange();
357 if (
Node* check = checks->LookupCheck(node,
jsgraph_)) {
368 if (control->
opcode() == IrOpcode::kLoop) {
377 int const input_count = node->op()->EffectInputCount();
378 for (
int i = 0;
i < input_count; ++
i) {
387 for (
int i = 1;
i < input_count; ++
i) {
405 if (checks ==
nullptr)
return NoChange();
417 if (
Node* check = checks->LookupBoundsCheckFor(first)) {
435 if (
Node* check = checks->LookupBoundsCheckFor(
second)) {
453 DCHECK(node->opcode() == IrOpcode::kSpeculativeNumberAdd ||
454 node->opcode() == IrOpcode::kSpeculativeNumberSubtract ||
455 node->opcode() == IrOpcode::kSpeculativeAdditiveSafeIntegerAdd ||
456 node->opcode() == IrOpcode::kSpeculativeAdditiveSafeIntegerSubtract ||
457 node->opcode() == IrOpcode::kSpeculativeSmallIntegerAdd ||
458 node->opcode() == IrOpcode::kSpeculativeSmallIntegerSubtract ||
459 node->opcode() == IrOpcode::kSpeculativeToNumber);
460 DCHECK_EQ(1, node->op()->EffectInputCount());
461 DCHECK_EQ(1, node->op()->EffectOutputCount());
468 if (checks ==
nullptr)
return NoChange();
474 if (
Node* check = checks->LookupBoundsCheckFor(first)) {
492 if (node->op()->EffectInputCount() == 1) {
493 if (node->op()->EffectOutputCount() == 1) {
500 DCHECK_EQ(0, node->op()->EffectInputCount());
501 DCHECK_EQ(0, node->op()->EffectOutputCount());
506 DCHECK_EQ(1, node->op()->EffectOutputCount());
511 if (checks ==
nullptr)
return NoChange();
522 if (checks != original) {
523 if (original ==
nullptr || !checks->
Equals(original)) {
void ReplaceWithValue(Node *node, Node *value, Node *effect=nullptr, Node *control=nullptr)
static Reduction Replace(Node *node)
CheckBoundsFlags flags() const
static Type GetType(const Node *node)
static bool IsTyped(const Node *node)
static Node * GetEffectInput(Node *node, int index=0)
static Node * GetValueInput(Node *node, int index)
static void ReplaceValueInput(Node *node, Node *value, int index)
static Node * GetControlInput(Node *node, int index=0)
constexpr IrOpcode::Value opcode() const
static Reduction Changed(Node *node)
static Reduction NoChange()
Reduction FollowedBy(Reduction next) const
EffectPathChecks const * AddCheck(Zone *zone, Node *node) const
static EffectPathChecks const * Empty(Zone *zone)
void Merge(EffectPathChecks const *that)
static EffectPathChecks * Copy(Zone *zone, EffectPathChecks const *checks)
Node * LookupBoundsCheckFor(Node *node) const
Node * LookupCheck(Node *node, JSGraph *jsgraph) const
bool Equals(EffectPathChecks const *that) const
EffectPathChecks const * Get(Node *node) const
void Set(Node *node, EffectPathChecks const *checks)
Reduction ReduceCheckNode(Node *node)
RedundancyElimination(Editor *editor, JSGraph *jsgraph, Zone *zone)
Reduction ReduceOtherNode(Node *node)
Reduction UpdateChecks(Node *node, EffectPathChecks const *checks)
PathChecksForEffectNodes node_checks_
Reduction Reduce(Node *node) final
Reduction ReduceSpeculativeNumberOperation(Node *node)
~RedundancyElimination() final
Reduction ReduceSpeculativeNumberComparison(Node *node)
Reduction TakeChecksFromFirstEffect(Node *node)
Reduction ReduceEffectPhi(Node *node)
Reduction ReduceStart(Node *node)
static Type UnsignedSmall()
ZoneVector< RpoNumber > & result
@ kConvertStringAndMinusZero
const CheckTaggedInputParameters & CheckTaggedInputParametersOf(const Operator *op)
const CheckMinusZeroParameters & CheckMinusZeroParametersOf(const Operator *op)
NumberOperationHint NumberOperationHintOf(const Operator *op)
CheckBoundsParameters const & CheckBoundsParametersOf(Operator const *op)
bool IsCheckedWithFeedback(const Operator *op)
bool Is(IndirectHandle< U > value)
#define SIMPLIFIED_BIGINT_BINOP_LIST(V)
#define SIMPLIFIED_CHECKED_OP_LIST(V)
#define SIMPLIFIED_OP(Opcode)
const Operator * conversion_op_
#define DCHECK_NOT_NULL(val)
#define DCHECK(condition)
#define DCHECK_LT(v1, v2)
#define DCHECK_EQ(v1, v2)