1// Copyright 2012 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "src/compiler/simplified-operator.h"
6
7#include "src/base/lazy-instance.h"
8#include "src/compiler/opcodes.h"
9#include "src/compiler/operator.h"
10#include "src/types.h"
11
12namespace v8 {
13namespace internal {
14namespace compiler {
15
16size_t hash_value(BaseTaggedness base_taggedness) {
17  return static_cast<uint8_t>(base_taggedness);
18}
19
20std::ostream& operator<<(std::ostream& os, BaseTaggedness base_taggedness) {
21  switch (base_taggedness) {
22    case kUntaggedBase:
23      return os << "untagged base";
24    case kTaggedBase:
25      return os << "tagged base";
26  }
27  UNREACHABLE();
28  return os;
29}
30
31
32MachineType BufferAccess::machine_type() const {
33  switch (external_array_type_) {
34    case kExternalUint8Array:
35    case kExternalUint8ClampedArray:
36      return MachineType::Uint8();
37    case kExternalInt8Array:
38      return MachineType::Int8();
39    case kExternalUint16Array:
40      return MachineType::Uint16();
41    case kExternalInt16Array:
42      return MachineType::Int16();
43    case kExternalUint32Array:
44      return MachineType::Uint32();
45    case kExternalInt32Array:
46      return MachineType::Int32();
47    case kExternalFloat32Array:
48      return MachineType::Float32();
49    case kExternalFloat64Array:
50      return MachineType::Float64();
51  }
52  UNREACHABLE();
53  return MachineType::None();
54}
55
56
57bool operator==(BufferAccess lhs, BufferAccess rhs) {
58  return lhs.external_array_type() == rhs.external_array_type();
59}
60
61
62bool operator!=(BufferAccess lhs, BufferAccess rhs) { return !(lhs == rhs); }
63
64
65size_t hash_value(BufferAccess access) {
66  return base::hash<ExternalArrayType>()(access.external_array_type());
67}
68
69
70std::ostream& operator<<(std::ostream& os, BufferAccess access) {
71  switch (access.external_array_type()) {
72#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
73  case kExternal##Type##Array:                          \
74    return os << #Type;
75    TYPED_ARRAYS(TYPED_ARRAY_CASE)
76#undef TYPED_ARRAY_CASE
77  }
78  UNREACHABLE();
79  return os;
80}
81
82
83BufferAccess const BufferAccessOf(const Operator* op) {
84  DCHECK(op->opcode() == IrOpcode::kLoadBuffer ||
85         op->opcode() == IrOpcode::kStoreBuffer);
86  return OpParameter<BufferAccess>(op);
87}
88
89
90bool operator==(FieldAccess const& lhs, FieldAccess const& rhs) {
91  // On purpose we don't include the write barrier kind here, as this method is
92  // really only relevant for eliminating loads and they don't care about the
93  // write barrier mode.
94  return lhs.base_is_tagged == rhs.base_is_tagged && lhs.offset == rhs.offset &&
95         lhs.machine_type == rhs.machine_type;
96}
97
98
99bool operator!=(FieldAccess const& lhs, FieldAccess const& rhs) {
100  return !(lhs == rhs);
101}
102
103
104size_t hash_value(FieldAccess const& access) {
105  // On purpose we don't include the write barrier kind here, as this method is
106  // really only relevant for eliminating loads and they don't care about the
107  // write barrier mode.
108  return base::hash_combine(access.base_is_tagged, access.offset,
109                            access.machine_type);
110}
111
112
113std::ostream& operator<<(std::ostream& os, FieldAccess const& access) {
114  os << "[" << access.base_is_tagged << ", " << access.offset << ", ";
115#ifdef OBJECT_PRINT
116  Handle<Name> name;
117  if (access.name.ToHandle(&name)) {
118    name->Print(os);
119    os << ", ";
120  }
121#endif
122  access.type->PrintTo(os);
123  os << ", " << access.machine_type << ", " << access.write_barrier_kind << "]";
124  return os;
125}
126
127
128bool operator==(ElementAccess const& lhs, ElementAccess const& rhs) {
129  // On purpose we don't include the write barrier kind here, as this method is
130  // really only relevant for eliminating loads and they don't care about the
131  // write barrier mode.
132  return lhs.base_is_tagged == rhs.base_is_tagged &&
133         lhs.header_size == rhs.header_size &&
134         lhs.machine_type == rhs.machine_type;
135}
136
137
138bool operator!=(ElementAccess const& lhs, ElementAccess const& rhs) {
139  return !(lhs == rhs);
140}
141
142
143size_t hash_value(ElementAccess const& access) {
144  // On purpose we don't include the write barrier kind here, as this method is
145  // really only relevant for eliminating loads and they don't care about the
146  // write barrier mode.
147  return base::hash_combine(access.base_is_tagged, access.header_size,
148                            access.machine_type);
149}
150
151
152std::ostream& operator<<(std::ostream& os, ElementAccess const& access) {
153  os << access.base_is_tagged << ", " << access.header_size << ", ";
154  access.type->PrintTo(os);
155  os << ", " << access.machine_type << ", " << access.write_barrier_kind;
156  return os;
157}
158
159
160const FieldAccess& FieldAccessOf(const Operator* op) {
161  DCHECK_NOT_NULL(op);
162  DCHECK(op->opcode() == IrOpcode::kLoadField ||
163         op->opcode() == IrOpcode::kStoreField);
164  return OpParameter<FieldAccess>(op);
165}
166
167
168const ElementAccess& ElementAccessOf(const Operator* op) {
169  DCHECK_NOT_NULL(op);
170  DCHECK(op->opcode() == IrOpcode::kLoadElement ||
171         op->opcode() == IrOpcode::kStoreElement);
172  return OpParameter<ElementAccess>(op);
173}
174
175size_t hash_value(CheckFloat64HoleMode mode) {
176  return static_cast<size_t>(mode);
177}
178
179std::ostream& operator<<(std::ostream& os, CheckFloat64HoleMode mode) {
180  switch (mode) {
181    case CheckFloat64HoleMode::kAllowReturnHole:
182      return os << "allow-return-hole";
183    case CheckFloat64HoleMode::kNeverReturnHole:
184      return os << "never-return-hole";
185  }
186  UNREACHABLE();
187  return os;
188}
189
190CheckFloat64HoleMode CheckFloat64HoleModeOf(const Operator* op) {
191  DCHECK_EQ(IrOpcode::kCheckFloat64Hole, op->opcode());
192  return OpParameter<CheckFloat64HoleMode>(op);
193}
194
195size_t hash_value(CheckTaggedHoleMode mode) {
196  return static_cast<size_t>(mode);
197}
198
199std::ostream& operator<<(std::ostream& os, CheckTaggedHoleMode mode) {
200  switch (mode) {
201    case CheckTaggedHoleMode::kConvertHoleToUndefined:
202      return os << "convert-hole-to-undefined";
203    case CheckTaggedHoleMode::kNeverReturnHole:
204      return os << "never-return-hole";
205  }
206  UNREACHABLE();
207  return os;
208}
209
210CheckTaggedHoleMode CheckTaggedHoleModeOf(const Operator* op) {
211  DCHECK_EQ(IrOpcode::kCheckTaggedHole, op->opcode());
212  return OpParameter<CheckTaggedHoleMode>(op);
213}
214
215Type* TypeOf(const Operator* op) {
216  DCHECK_EQ(IrOpcode::kTypeGuard, op->opcode());
217  return OpParameter<Type*>(op);
218}
219
220BinaryOperationHints::Hint BinaryOperationHintOf(const Operator* op) {
221  DCHECK(op->opcode() == IrOpcode::kSpeculativeNumberAdd ||
222         op->opcode() == IrOpcode::kSpeculativeNumberSubtract ||
223         op->opcode() == IrOpcode::kSpeculativeNumberMultiply ||
224         op->opcode() == IrOpcode::kSpeculativeNumberDivide ||
225         op->opcode() == IrOpcode::kSpeculativeNumberModulus);
226  return OpParameter<BinaryOperationHints::Hint>(op);
227}
228
229CompareOperationHints::Hint CompareOperationHintOf(const Operator* op) {
230  DCHECK(op->opcode() == IrOpcode::kSpeculativeNumberEqual ||
231         op->opcode() == IrOpcode::kSpeculativeNumberLessThan ||
232         op->opcode() == IrOpcode::kSpeculativeNumberLessThanOrEqual);
233  return OpParameter<CompareOperationHints::Hint>(op);
234}
235
236#define PURE_OP_LIST(V)                                    \
237  V(BooleanNot, Operator::kNoProperties, 1)                \
238  V(BooleanToNumber, Operator::kNoProperties, 1)           \
239  V(NumberEqual, Operator::kCommutative, 2)                \
240  V(NumberLessThan, Operator::kNoProperties, 2)            \
241  V(NumberLessThanOrEqual, Operator::kNoProperties, 2)     \
242  V(NumberAdd, Operator::kCommutative, 2)                  \
243  V(NumberSubtract, Operator::kNoProperties, 2)            \
244  V(NumberMultiply, Operator::kCommutative, 2)             \
245  V(NumberDivide, Operator::kNoProperties, 2)              \
246  V(NumberModulus, Operator::kNoProperties, 2)             \
247  V(NumberBitwiseOr, Operator::kCommutative, 2)            \
248  V(NumberBitwiseXor, Operator::kCommutative, 2)           \
249  V(NumberBitwiseAnd, Operator::kCommutative, 2)           \
250  V(NumberShiftLeft, Operator::kNoProperties, 2)           \
251  V(NumberShiftRight, Operator::kNoProperties, 2)          \
252  V(NumberShiftRightLogical, Operator::kNoProperties, 2)   \
253  V(NumberImul, Operator::kCommutative, 2)                 \
254  V(NumberAbs, Operator::kNoProperties, 1)                 \
255  V(NumberClz32, Operator::kNoProperties, 1)               \
256  V(NumberCeil, Operator::kNoProperties, 1)                \
257  V(NumberFloor, Operator::kNoProperties, 1)               \
258  V(NumberFround, Operator::kNoProperties, 1)              \
259  V(NumberAtan, Operator::kNoProperties, 1)                \
260  V(NumberAtan2, Operator::kNoProperties, 2)               \
261  V(NumberAtanh, Operator::kNoProperties, 1)               \
262  V(NumberCbrt, Operator::kNoProperties, 1)                \
263  V(NumberCos, Operator::kNoProperties, 1)                 \
264  V(NumberExp, Operator::kNoProperties, 1)                 \
265  V(NumberExpm1, Operator::kNoProperties, 1)               \
266  V(NumberLog, Operator::kNoProperties, 1)                 \
267  V(NumberLog1p, Operator::kNoProperties, 1)               \
268  V(NumberLog10, Operator::kNoProperties, 1)               \
269  V(NumberLog2, Operator::kNoProperties, 1)                \
270  V(NumberRound, Operator::kNoProperties, 1)               \
271  V(NumberSin, Operator::kNoProperties, 1)                 \
272  V(NumberSqrt, Operator::kNoProperties, 1)                \
273  V(NumberTan, Operator::kNoProperties, 1)                 \
274  V(NumberTrunc, Operator::kNoProperties, 1)               \
275  V(NumberToInt32, Operator::kNoProperties, 1)             \
276  V(NumberToUint32, Operator::kNoProperties, 1)            \
277  V(NumberSilenceNaN, Operator::kNoProperties, 1)          \
278  V(StringFromCharCode, Operator::kNoProperties, 1)        \
279  V(StringToNumber, Operator::kNoProperties, 1)            \
280  V(PlainPrimitiveToNumber, Operator::kNoProperties, 1)    \
281  V(PlainPrimitiveToWord32, Operator::kNoProperties, 1)    \
282  V(PlainPrimitiveToFloat64, Operator::kNoProperties, 1)   \
283  V(ChangeTaggedSignedToInt32, Operator::kNoProperties, 1) \
284  V(ChangeTaggedToInt32, Operator::kNoProperties, 1)       \
285  V(ChangeTaggedToUint32, Operator::kNoProperties, 1)      \
286  V(ChangeTaggedToFloat64, Operator::kNoProperties, 1)     \
287  V(ChangeInt31ToTaggedSigned, Operator::kNoProperties, 1) \
288  V(ChangeInt32ToTagged, Operator::kNoProperties, 1)       \
289  V(ChangeUint32ToTagged, Operator::kNoProperties, 1)      \
290  V(ChangeFloat64ToTagged, Operator::kNoProperties, 1)     \
291  V(ChangeTaggedToBit, Operator::kNoProperties, 1)         \
292  V(ChangeBitToTagged, Operator::kNoProperties, 1)         \
293  V(TruncateTaggedToWord32, Operator::kNoProperties, 1)    \
294  V(TruncateTaggedToFloat64, Operator::kNoProperties, 1)   \
295  V(ObjectIsCallable, Operator::kNoProperties, 1)          \
296  V(ObjectIsNumber, Operator::kNoProperties, 1)            \
297  V(ObjectIsReceiver, Operator::kNoProperties, 1)          \
298  V(ObjectIsSmi, Operator::kNoProperties, 1)               \
299  V(ObjectIsString, Operator::kNoProperties, 1)            \
300  V(ObjectIsUndetectable, Operator::kNoProperties, 1)      \
301  V(StringEqual, Operator::kCommutative, 2)                \
302  V(StringLessThan, Operator::kNoProperties, 2)            \
303  V(StringLessThanOrEqual, Operator::kNoProperties, 2)
304
305#define SPECULATIVE_BINOP_LIST(V) \
306  V(SpeculativeNumberAdd)         \
307  V(SpeculativeNumberSubtract)    \
308  V(SpeculativeNumberDivide)      \
309  V(SpeculativeNumberMultiply)    \
310  V(SpeculativeNumberModulus)
311
312#define CHECKED_OP_LIST(V)    \
313  V(CheckTaggedPointer, 1)    \
314  V(CheckTaggedSigned, 1)     \
315  V(CheckedInt32Add, 2)       \
316  V(CheckedInt32Sub, 2)       \
317  V(CheckedUint32ToInt32, 1)  \
318  V(CheckedFloat64ToInt32, 1) \
319  V(CheckedTaggedToInt32, 1)  \
320  V(CheckedTaggedToFloat64, 1)
321
322struct SimplifiedOperatorGlobalCache final {
323#define PURE(Name, properties, input_count)                                \
324  struct Name##Operator final : public Operator {                          \
325    Name##Operator()                                                       \
326        : Operator(IrOpcode::k##Name, Operator::kPure | properties, #Name, \
327                   input_count, 0, 0, 1, 0, 0) {}                          \
328  };                                                                       \
329  Name##Operator k##Name;
330  PURE_OP_LIST(PURE)
331#undef PURE
332
333#define CHECKED(Name, value_input_count)                            \
334  struct Name##Operator final : public Operator {                   \
335    Name##Operator()                                                \
336        : Operator(IrOpcode::k##Name,                               \
337                   Operator::kFoldable | Operator::kNoThrow, #Name, \
338                   value_input_count, 1, 1, 1, 1, 0) {}             \
339  };                                                                \
340  Name##Operator k##Name;
341  CHECKED_OP_LIST(CHECKED)
342#undef CHECKED
343
344  template <CheckFloat64HoleMode kMode>
345  struct CheckFloat64HoleNaNOperator final
346      : public Operator1<CheckFloat64HoleMode> {
347    CheckFloat64HoleNaNOperator()
348        : Operator1<CheckFloat64HoleMode>(
349              IrOpcode::kCheckFloat64Hole,
350              Operator::kFoldable | Operator::kNoThrow, "CheckFloat64Hole", 1,
351              1, 1, 1, 1, 0, kMode) {}
352  };
353  CheckFloat64HoleNaNOperator<CheckFloat64HoleMode::kAllowReturnHole>
354      kCheckFloat64HoleAllowReturnHoleOperator;
355  CheckFloat64HoleNaNOperator<CheckFloat64HoleMode::kNeverReturnHole>
356      kCheckFloat64HoleNeverReturnHoleOperator;
357
358  template <CheckTaggedHoleMode kMode>
359  struct CheckTaggedHoleOperator final : public Operator1<CheckTaggedHoleMode> {
360    CheckTaggedHoleOperator()
361        : Operator1<CheckTaggedHoleMode>(
362              IrOpcode::kCheckTaggedHole,
363              Operator::kFoldable | Operator::kNoThrow, "CheckTaggedHole", 1, 1,
364              1, 1, 1, 0, kMode) {}
365  };
366  CheckTaggedHoleOperator<CheckTaggedHoleMode::kConvertHoleToUndefined>
367      kCheckTaggedHoleConvertHoleToUndefinedOperator;
368  CheckTaggedHoleOperator<CheckTaggedHoleMode::kNeverReturnHole>
369      kCheckTaggedHoleNeverReturnHoleOperator;
370
371  template <PretenureFlag kPretenure>
372  struct AllocateOperator final : public Operator1<PretenureFlag> {
373    AllocateOperator()
374        : Operator1<PretenureFlag>(
375              IrOpcode::kAllocate,
376              Operator::kNoDeopt | Operator::kNoThrow | Operator::kNoWrite,
377              "Allocate", 1, 1, 1, 1, 1, 0, kPretenure) {}
378  };
379  AllocateOperator<NOT_TENURED> kAllocateNotTenuredOperator;
380  AllocateOperator<TENURED> kAllocateTenuredOperator;
381
382#define BUFFER_ACCESS(Type, type, TYPE, ctype, size)                          \
383  struct LoadBuffer##Type##Operator final : public Operator1<BufferAccess> {  \
384    LoadBuffer##Type##Operator()                                              \
385        : Operator1<BufferAccess>(                                            \
386              IrOpcode::kLoadBuffer,                                          \
387              Operator::kNoDeopt | Operator::kNoThrow | Operator::kNoWrite,   \
388              "LoadBuffer", 3, 1, 1, 1, 1, 0,                                 \
389              BufferAccess(kExternal##Type##Array)) {}                        \
390  };                                                                          \
391  struct StoreBuffer##Type##Operator final : public Operator1<BufferAccess> { \
392    StoreBuffer##Type##Operator()                                             \
393        : Operator1<BufferAccess>(                                            \
394              IrOpcode::kStoreBuffer,                                         \
395              Operator::kNoDeopt | Operator::kNoRead | Operator::kNoThrow,    \
396              "StoreBuffer", 4, 1, 1, 0, 1, 0,                                \
397              BufferAccess(kExternal##Type##Array)) {}                        \
398  };                                                                          \
399  LoadBuffer##Type##Operator kLoadBuffer##Type;                               \
400  StoreBuffer##Type##Operator kStoreBuffer##Type;
401  TYPED_ARRAYS(BUFFER_ACCESS)
402#undef BUFFER_ACCESS
403};
404
405
406static base::LazyInstance<SimplifiedOperatorGlobalCache>::type kCache =
407    LAZY_INSTANCE_INITIALIZER;
408
409
410SimplifiedOperatorBuilder::SimplifiedOperatorBuilder(Zone* zone)
411    : cache_(kCache.Get()), zone_(zone) {}
412
413#define GET_FROM_CACHE(Name, properties, input_count) \
414  const Operator* SimplifiedOperatorBuilder::Name() { return &cache_.k##Name; }
415PURE_OP_LIST(GET_FROM_CACHE)
416#undef GET_FROM_CACHE
417
418#define GET_FROM_CACHE(Name, value_input_count) \
419  const Operator* SimplifiedOperatorBuilder::Name() { return &cache_.k##Name; }
420CHECKED_OP_LIST(GET_FROM_CACHE)
421#undef GET_FROM_CACHE
422
423const Operator* SimplifiedOperatorBuilder::CheckFloat64Hole(
424    CheckFloat64HoleMode mode) {
425  switch (mode) {
426    case CheckFloat64HoleMode::kAllowReturnHole:
427      return &cache_.kCheckFloat64HoleAllowReturnHoleOperator;
428    case CheckFloat64HoleMode::kNeverReturnHole:
429      return &cache_.kCheckFloat64HoleNeverReturnHoleOperator;
430  }
431  UNREACHABLE();
432  return nullptr;
433}
434
435const Operator* SimplifiedOperatorBuilder::CheckTaggedHole(
436    CheckTaggedHoleMode mode) {
437  switch (mode) {
438    case CheckTaggedHoleMode::kConvertHoleToUndefined:
439      return &cache_.kCheckTaggedHoleConvertHoleToUndefinedOperator;
440    case CheckTaggedHoleMode::kNeverReturnHole:
441      return &cache_.kCheckTaggedHoleNeverReturnHoleOperator;
442  }
443  UNREACHABLE();
444  return nullptr;
445}
446
447const Operator* SimplifiedOperatorBuilder::ReferenceEqual(Type* type) {
448  return new (zone()) Operator(IrOpcode::kReferenceEqual,
449                               Operator::kCommutative | Operator::kPure,
450                               "ReferenceEqual", 2, 0, 0, 1, 0, 0);
451}
452
453const Operator* SimplifiedOperatorBuilder::CheckBounds() {
454  // TODO(bmeurer): Cache this operator. Make it pure!
455  return new (zone())
456      Operator(IrOpcode::kCheckBounds, Operator::kFoldable | Operator::kNoThrow,
457               "CheckBounds", 2, 1, 1, 1, 1, 0);
458}
459
460const Operator* SimplifiedOperatorBuilder::TypeGuard(Type* type) {
461  class TypeGuardOperator final : public Operator1<Type*> {
462   public:
463    explicit TypeGuardOperator(Type* type)
464        : Operator1<Type*>(                           // --
465              IrOpcode::kTypeGuard, Operator::kPure,  // opcode
466              "TypeGuard",                            // name
467              1, 0, 1, 1, 0, 0,                       // counts
468              type) {}                                // parameter
469
470    void PrintParameter(std::ostream& os) const final {
471      parameter()->PrintTo(os);
472    }
473  };
474  return new (zone()) TypeGuardOperator(type);
475}
476
477const Operator* SimplifiedOperatorBuilder::Allocate(PretenureFlag pretenure) {
478  switch (pretenure) {
479    case NOT_TENURED:
480      return &cache_.kAllocateNotTenuredOperator;
481    case TENURED:
482      return &cache_.kAllocateTenuredOperator;
483  }
484  UNREACHABLE();
485  return nullptr;
486}
487
488
489const Operator* SimplifiedOperatorBuilder::LoadBuffer(BufferAccess access) {
490  switch (access.external_array_type()) {
491#define LOAD_BUFFER(Type, type, TYPE, ctype, size) \
492  case kExternal##Type##Array:                     \
493    return &cache_.kLoadBuffer##Type;
494    TYPED_ARRAYS(LOAD_BUFFER)
495#undef LOAD_BUFFER
496  }
497  UNREACHABLE();
498  return nullptr;
499}
500
501
502const Operator* SimplifiedOperatorBuilder::StoreBuffer(BufferAccess access) {
503  switch (access.external_array_type()) {
504#define STORE_BUFFER(Type, type, TYPE, ctype, size) \
505  case kExternal##Type##Array:                      \
506    return &cache_.kStoreBuffer##Type;
507    TYPED_ARRAYS(STORE_BUFFER)
508#undef STORE_BUFFER
509  }
510  UNREACHABLE();
511  return nullptr;
512}
513
514#define SPECULATIVE_BINOP_DEF(Name)                                            \
515  const Operator* SimplifiedOperatorBuilder::Name(                             \
516      BinaryOperationHints::Hint hint) {                                       \
517    return new (zone()) Operator1<BinaryOperationHints::Hint>(                 \
518        IrOpcode::k##Name, Operator::kFoldable | Operator::kNoThrow, #Name, 2, \
519        1, 1, 1, 1, 0, hint);                                                  \
520  }
521SPECULATIVE_BINOP_LIST(SPECULATIVE_BINOP_DEF)
522#undef SPECULATIVE_BINOP_DEF
523
524const Operator* SimplifiedOperatorBuilder::SpeculativeNumberEqual(
525    CompareOperationHints::Hint hint) {
526  return new (zone()) Operator1<CompareOperationHints::Hint>(
527      IrOpcode::kSpeculativeNumberEqual,
528      Operator::kFoldable | Operator::kNoThrow, "SpeculativeNumberEqual", 2, 1,
529      1, 1, 1, 0, hint);
530}
531
532const Operator* SimplifiedOperatorBuilder::SpeculativeNumberLessThan(
533    CompareOperationHints::Hint hint) {
534  return new (zone()) Operator1<CompareOperationHints::Hint>(
535      IrOpcode::kSpeculativeNumberLessThan,
536      Operator::kFoldable | Operator::kNoThrow, "SpeculativeNumberLessThan", 2,
537      1, 1, 1, 1, 0, hint);
538}
539
540const Operator* SimplifiedOperatorBuilder::SpeculativeNumberLessThanOrEqual(
541    CompareOperationHints::Hint hint) {
542  return new (zone()) Operator1<CompareOperationHints::Hint>(
543      IrOpcode::kSpeculativeNumberLessThanOrEqual,
544      Operator::kFoldable | Operator::kNoThrow,
545      "SpeculativeNumberLessThanOrEqual", 2, 1, 1, 1, 1, 0, hint);
546}
547
548#define ACCESS_OP_LIST(V)                                    \
549  V(LoadField, FieldAccess, Operator::kNoWrite, 1, 1, 1)     \
550  V(StoreField, FieldAccess, Operator::kNoRead, 2, 1, 0)     \
551  V(LoadElement, ElementAccess, Operator::kNoWrite, 2, 1, 1) \
552  V(StoreElement, ElementAccess, Operator::kNoRead, 3, 1, 0)
553
554#define ACCESS(Name, Type, properties, value_input_count, control_input_count, \
555               output_count)                                                   \
556  const Operator* SimplifiedOperatorBuilder::Name(const Type& access) {        \
557    return new (zone())                                                        \
558        Operator1<Type>(IrOpcode::k##Name,                                     \
559                        Operator::kNoDeopt | Operator::kNoThrow | properties,  \
560                        #Name, value_input_count, 1, control_input_count,      \
561                        output_count, 1, 0, access);                           \
562  }
563ACCESS_OP_LIST(ACCESS)
564#undef ACCESS
565
566}  // namespace compiler
567}  // namespace internal
568}  // namespace v8
569