Home | History | Annotate | Download | only in compiler
      1 // Copyright 2014 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/machine-operator.h"
      6 
      7 #include "src/base/lazy-instance.h"
      8 #include "src/compiler/opcodes.h"
      9 #include "src/compiler/operator.h"
     10 
     11 namespace v8 {
     12 namespace internal {
     13 namespace compiler {
     14 
     15 std::ostream& operator<<(std::ostream& os, TruncationMode mode) {
     16   switch (mode) {
     17     case TruncationMode::kJavaScript:
     18       return os << "JavaScript";
     19     case TruncationMode::kRoundToZero:
     20       return os << "RoundToZero";
     21   }
     22   UNREACHABLE();
     23   return os;
     24 }
     25 
     26 
     27 TruncationMode TruncationModeOf(Operator const* op) {
     28   DCHECK_EQ(IrOpcode::kTruncateFloat64ToInt32, op->opcode());
     29   return OpParameter<TruncationMode>(op);
     30 }
     31 
     32 
     33 std::ostream& operator<<(std::ostream& os, WriteBarrierKind kind) {
     34   switch (kind) {
     35     case kNoWriteBarrier:
     36       return os << "NoWriteBarrier";
     37     case kMapWriteBarrier:
     38       return os << "MapWriteBarrier";
     39     case kPointerWriteBarrier:
     40       return os << "PointerWriteBarrier";
     41     case kFullWriteBarrier:
     42       return os << "FullWriteBarrier";
     43   }
     44   UNREACHABLE();
     45   return os;
     46 }
     47 
     48 
     49 bool operator==(StoreRepresentation lhs, StoreRepresentation rhs) {
     50   return lhs.representation() == rhs.representation() &&
     51          lhs.write_barrier_kind() == rhs.write_barrier_kind();
     52 }
     53 
     54 
     55 bool operator!=(StoreRepresentation lhs, StoreRepresentation rhs) {
     56   return !(lhs == rhs);
     57 }
     58 
     59 
     60 size_t hash_value(StoreRepresentation rep) {
     61   return base::hash_combine(rep.representation(), rep.write_barrier_kind());
     62 }
     63 
     64 
     65 std::ostream& operator<<(std::ostream& os, StoreRepresentation rep) {
     66   return os << "(" << rep.representation() << " : " << rep.write_barrier_kind()
     67             << ")";
     68 }
     69 
     70 
     71 LoadRepresentation LoadRepresentationOf(Operator const* op) {
     72   DCHECK_EQ(IrOpcode::kLoad, op->opcode());
     73   return OpParameter<LoadRepresentation>(op);
     74 }
     75 
     76 
     77 StoreRepresentation const& StoreRepresentationOf(Operator const* op) {
     78   DCHECK_EQ(IrOpcode::kStore, op->opcode());
     79   return OpParameter<StoreRepresentation>(op);
     80 }
     81 
     82 
     83 CheckedLoadRepresentation CheckedLoadRepresentationOf(Operator const* op) {
     84   DCHECK_EQ(IrOpcode::kCheckedLoad, op->opcode());
     85   return OpParameter<CheckedLoadRepresentation>(op);
     86 }
     87 
     88 
     89 CheckedStoreRepresentation CheckedStoreRepresentationOf(Operator const* op) {
     90   DCHECK_EQ(IrOpcode::kCheckedStore, op->opcode());
     91   return OpParameter<CheckedStoreRepresentation>(op);
     92 }
     93 
     94 
     95 #define PURE_OP_LIST(V)                                                       \
     96   V(Word32And, Operator::kAssociative | Operator::kCommutative, 2, 0, 1)      \
     97   V(Word32Or, Operator::kAssociative | Operator::kCommutative, 2, 0, 1)       \
     98   V(Word32Xor, Operator::kAssociative | Operator::kCommutative, 2, 0, 1)      \
     99   V(Word32Shl, Operator::kNoProperties, 2, 0, 1)                              \
    100   V(Word32Shr, Operator::kNoProperties, 2, 0, 1)                              \
    101   V(Word32Sar, Operator::kNoProperties, 2, 0, 1)                              \
    102   V(Word32Ror, Operator::kNoProperties, 2, 0, 1)                              \
    103   V(Word32Equal, Operator::kCommutative, 2, 0, 1)                             \
    104   V(Word32Clz, Operator::kNoProperties, 1, 0, 1)                              \
    105   V(Word64And, Operator::kAssociative | Operator::kCommutative, 2, 0, 1)      \
    106   V(Word64Or, Operator::kAssociative | Operator::kCommutative, 2, 0, 1)       \
    107   V(Word64Xor, Operator::kAssociative | Operator::kCommutative, 2, 0, 1)      \
    108   V(Word64Shl, Operator::kNoProperties, 2, 0, 1)                              \
    109   V(Word64Shr, Operator::kNoProperties, 2, 0, 1)                              \
    110   V(Word64Sar, Operator::kNoProperties, 2, 0, 1)                              \
    111   V(Word64Ror, Operator::kNoProperties, 2, 0, 1)                              \
    112   V(Word64Clz, Operator::kNoProperties, 1, 0, 1)                              \
    113   V(Word64Equal, Operator::kCommutative, 2, 0, 1)                             \
    114   V(Int32Add, Operator::kAssociative | Operator::kCommutative, 2, 0, 1)       \
    115   V(Int32AddWithOverflow, Operator::kAssociative | Operator::kCommutative, 2, \
    116     0, 2)                                                                     \
    117   V(Int32Sub, Operator::kNoProperties, 2, 0, 1)                               \
    118   V(Int32SubWithOverflow, Operator::kNoProperties, 2, 0, 2)                   \
    119   V(Int32Mul, Operator::kAssociative | Operator::kCommutative, 2, 0, 1)       \
    120   V(Int32MulHigh, Operator::kAssociative | Operator::kCommutative, 2, 0, 1)   \
    121   V(Int32Div, Operator::kNoProperties, 2, 1, 1)                               \
    122   V(Int32Mod, Operator::kNoProperties, 2, 1, 1)                               \
    123   V(Int32LessThan, Operator::kNoProperties, 2, 0, 1)                          \
    124   V(Int32LessThanOrEqual, Operator::kNoProperties, 2, 0, 1)                   \
    125   V(Uint32Div, Operator::kNoProperties, 2, 1, 1)                              \
    126   V(Uint32LessThan, Operator::kNoProperties, 2, 0, 1)                         \
    127   V(Uint32LessThanOrEqual, Operator::kNoProperties, 2, 0, 1)                  \
    128   V(Uint32Mod, Operator::kNoProperties, 2, 1, 1)                              \
    129   V(Uint32MulHigh, Operator::kAssociative | Operator::kCommutative, 2, 0, 1)  \
    130   V(Int64Add, Operator::kAssociative | Operator::kCommutative, 2, 0, 1)       \
    131   V(Int64AddWithOverflow, Operator::kAssociative | Operator::kCommutative, 2, \
    132     0, 2)                                                                     \
    133   V(Int64Sub, Operator::kNoProperties, 2, 0, 1)                               \
    134   V(Int64SubWithOverflow, Operator::kNoProperties, 2, 0, 2)                   \
    135   V(Int64Mul, Operator::kAssociative | Operator::kCommutative, 2, 0, 1)       \
    136   V(Int64Div, Operator::kNoProperties, 2, 1, 1)                               \
    137   V(Int64Mod, Operator::kNoProperties, 2, 1, 1)                               \
    138   V(Int64LessThan, Operator::kNoProperties, 2, 0, 1)                          \
    139   V(Int64LessThanOrEqual, Operator::kNoProperties, 2, 0, 1)                   \
    140   V(Uint64Div, Operator::kNoProperties, 2, 1, 1)                              \
    141   V(Uint64Mod, Operator::kNoProperties, 2, 1, 1)                              \
    142   V(Uint64LessThan, Operator::kNoProperties, 2, 0, 1)                         \
    143   V(Uint64LessThanOrEqual, Operator::kNoProperties, 2, 0, 1)                  \
    144   V(ChangeFloat32ToFloat64, Operator::kNoProperties, 1, 0, 1)                 \
    145   V(ChangeFloat64ToInt32, Operator::kNoProperties, 1, 0, 1)                   \
    146   V(ChangeFloat64ToUint32, Operator::kNoProperties, 1, 0, 1)                  \
    147   V(TryTruncateFloat32ToInt64, Operator::kNoProperties, 1, 0, 2)              \
    148   V(TryTruncateFloat64ToInt64, Operator::kNoProperties, 1, 0, 2)              \
    149   V(TryTruncateFloat32ToUint64, Operator::kNoProperties, 1, 0, 2)             \
    150   V(TryTruncateFloat64ToUint64, Operator::kNoProperties, 1, 0, 2)             \
    151   V(ChangeInt32ToFloat64, Operator::kNoProperties, 1, 0, 1)                   \
    152   V(RoundInt64ToFloat32, Operator::kNoProperties, 1, 0, 1)                    \
    153   V(RoundInt64ToFloat64, Operator::kNoProperties, 1, 0, 1)                    \
    154   V(RoundUint64ToFloat32, Operator::kNoProperties, 1, 0, 1)                   \
    155   V(RoundUint64ToFloat64, Operator::kNoProperties, 1, 0, 1)                   \
    156   V(ChangeInt32ToInt64, Operator::kNoProperties, 1, 0, 1)                     \
    157   V(ChangeUint32ToFloat64, Operator::kNoProperties, 1, 0, 1)                  \
    158   V(ChangeUint32ToUint64, Operator::kNoProperties, 1, 0, 1)                   \
    159   V(TruncateFloat64ToFloat32, Operator::kNoProperties, 1, 0, 1)               \
    160   V(TruncateInt64ToInt32, Operator::kNoProperties, 1, 0, 1)                   \
    161   V(BitcastFloat32ToInt32, Operator::kNoProperties, 1, 0, 1)                  \
    162   V(BitcastFloat64ToInt64, Operator::kNoProperties, 1, 0, 1)                  \
    163   V(BitcastInt32ToFloat32, Operator::kNoProperties, 1, 0, 1)                  \
    164   V(BitcastInt64ToFloat64, Operator::kNoProperties, 1, 0, 1)                  \
    165   V(Float32Abs, Operator::kNoProperties, 1, 0, 1)                             \
    166   V(Float32Add, Operator::kCommutative, 2, 0, 1)                              \
    167   V(Float32Sub, Operator::kNoProperties, 2, 0, 1)                             \
    168   V(Float32Mul, Operator::kCommutative, 2, 0, 1)                              \
    169   V(Float32Div, Operator::kNoProperties, 2, 0, 1)                             \
    170   V(Float32Sqrt, Operator::kNoProperties, 1, 0, 1)                            \
    171   V(Float64Abs, Operator::kNoProperties, 1, 0, 1)                             \
    172   V(Float64Add, Operator::kCommutative, 2, 0, 1)                              \
    173   V(Float64Sub, Operator::kNoProperties, 2, 0, 1)                             \
    174   V(Float64Mul, Operator::kCommutative, 2, 0, 1)                              \
    175   V(Float64Div, Operator::kNoProperties, 2, 0, 1)                             \
    176   V(Float64Mod, Operator::kNoProperties, 2, 0, 1)                             \
    177   V(Float64Sqrt, Operator::kNoProperties, 1, 0, 1)                            \
    178   V(Float32Equal, Operator::kCommutative, 2, 0, 1)                            \
    179   V(Float32LessThan, Operator::kNoProperties, 2, 0, 1)                        \
    180   V(Float32LessThanOrEqual, Operator::kNoProperties, 2, 0, 1)                 \
    181   V(Float64Equal, Operator::kCommutative, 2, 0, 1)                            \
    182   V(Float64LessThan, Operator::kNoProperties, 2, 0, 1)                        \
    183   V(Float64LessThanOrEqual, Operator::kNoProperties, 2, 0, 1)                 \
    184   V(Float64ExtractLowWord32, Operator::kNoProperties, 1, 0, 1)                \
    185   V(Float64ExtractHighWord32, Operator::kNoProperties, 1, 0, 1)               \
    186   V(Float64InsertLowWord32, Operator::kNoProperties, 2, 0, 1)                 \
    187   V(Float64InsertHighWord32, Operator::kNoProperties, 2, 0, 1)                \
    188   V(LoadStackPointer, Operator::kNoProperties, 0, 0, 1)                       \
    189   V(LoadFramePointer, Operator::kNoProperties, 0, 0, 1)
    190 
    191 #define PURE_OPTIONAL_OP_LIST(V)                            \
    192   V(Word32Ctz, Operator::kNoProperties, 1, 0, 1)            \
    193   V(Word64Ctz, Operator::kNoProperties, 1, 0, 1)            \
    194   V(Word32Popcnt, Operator::kNoProperties, 1, 0, 1)         \
    195   V(Word64Popcnt, Operator::kNoProperties, 1, 0, 1)         \
    196   V(Float32Max, Operator::kNoProperties, 2, 0, 1)           \
    197   V(Float32Min, Operator::kNoProperties, 2, 0, 1)           \
    198   V(Float64Max, Operator::kNoProperties, 2, 0, 1)           \
    199   V(Float64Min, Operator::kNoProperties, 2, 0, 1)           \
    200   V(Float32RoundDown, Operator::kNoProperties, 1, 0, 1)     \
    201   V(Float64RoundDown, Operator::kNoProperties, 1, 0, 1)     \
    202   V(Float32RoundUp, Operator::kNoProperties, 1, 0, 1)       \
    203   V(Float64RoundUp, Operator::kNoProperties, 1, 0, 1)       \
    204   V(Float32RoundTruncate, Operator::kNoProperties, 1, 0, 1) \
    205   V(Float64RoundTruncate, Operator::kNoProperties, 1, 0, 1) \
    206   V(Float64RoundTiesAway, Operator::kNoProperties, 1, 0, 1) \
    207   V(Float32RoundTiesEven, Operator::kNoProperties, 1, 0, 1) \
    208   V(Float64RoundTiesEven, Operator::kNoProperties, 1, 0, 1)
    209 
    210 
    211 #define MACHINE_TYPE_LIST(V) \
    212   V(Float32)                 \
    213   V(Float64)                 \
    214   V(Int8)                    \
    215   V(Uint8)                   \
    216   V(Int16)                   \
    217   V(Uint16)                  \
    218   V(Int32)                   \
    219   V(Uint32)                  \
    220   V(Int64)                   \
    221   V(Uint64)                  \
    222   V(Pointer)                 \
    223   V(AnyTagged)
    224 
    225 
    226 #define MACHINE_REPRESENTATION_LIST(V) \
    227   V(kFloat32)                          \
    228   V(kFloat64)                          \
    229   V(kWord8)                            \
    230   V(kWord16)                           \
    231   V(kWord32)                           \
    232   V(kWord64)                           \
    233   V(kTagged)
    234 
    235 
    236 struct MachineOperatorGlobalCache {
    237 #define PURE(Name, properties, value_input_count, control_input_count,         \
    238              output_count)                                                     \
    239   struct Name##Operator final : public Operator {                              \
    240     Name##Operator()                                                           \
    241         : Operator(IrOpcode::k##Name, Operator::kPure | properties, #Name,     \
    242                    value_input_count, 0, control_input_count, output_count, 0, \
    243                    0) {}                                                       \
    244   };                                                                           \
    245   Name##Operator k##Name;
    246   PURE_OP_LIST(PURE)
    247   PURE_OPTIONAL_OP_LIST(PURE)
    248 #undef PURE
    249 
    250   template <TruncationMode kMode>
    251   struct TruncateFloat64ToInt32Operator final
    252       : public Operator1<TruncationMode> {
    253     TruncateFloat64ToInt32Operator()
    254         : Operator1<TruncationMode>(IrOpcode::kTruncateFloat64ToInt32,
    255                                     Operator::kPure, "TruncateFloat64ToInt32",
    256                                     1, 0, 0, 1, 0, 0, kMode) {}
    257   };
    258   TruncateFloat64ToInt32Operator<TruncationMode::kJavaScript>
    259       kTruncateFloat64ToInt32JavaScript;
    260   TruncateFloat64ToInt32Operator<TruncationMode::kRoundToZero>
    261       kTruncateFloat64ToInt32RoundToZero;
    262 
    263 #define LOAD(Type)                                                             \
    264   struct Load##Type##Operator final : public Operator1<LoadRepresentation> {   \
    265     Load##Type##Operator()                                                     \
    266         : Operator1<LoadRepresentation>(                                       \
    267               IrOpcode::kLoad, Operator::kNoThrow | Operator::kNoWrite,        \
    268               "Load", 2, 1, 1, 1, 1, 0, MachineType::Type()) {}                \
    269   };                                                                           \
    270   struct CheckedLoad##Type##Operator final                                     \
    271       : public Operator1<CheckedLoadRepresentation> {                          \
    272     CheckedLoad##Type##Operator()                                              \
    273         : Operator1<CheckedLoadRepresentation>(                                \
    274               IrOpcode::kCheckedLoad, Operator::kNoThrow | Operator::kNoWrite, \
    275               "CheckedLoad", 3, 1, 1, 1, 1, 0, MachineType::Type()) {}         \
    276   };                                                                           \
    277   Load##Type##Operator kLoad##Type;                                            \
    278   CheckedLoad##Type##Operator kCheckedLoad##Type;
    279   MACHINE_TYPE_LIST(LOAD)
    280 #undef LOAD
    281 
    282 #define STORE(Type)                                                            \
    283   struct Store##Type##Operator : public Operator1<StoreRepresentation> {       \
    284     explicit Store##Type##Operator(WriteBarrierKind write_barrier_kind)        \
    285         : Operator1<StoreRepresentation>(                                      \
    286               IrOpcode::kStore, Operator::kNoRead | Operator::kNoThrow,        \
    287               "Store", 3, 1, 1, 0, 1, 0,                                       \
    288               StoreRepresentation(MachineRepresentation::Type,                 \
    289                                   write_barrier_kind)) {}                      \
    290   };                                                                           \
    291   struct Store##Type##NoWriteBarrier##Operator final                           \
    292       : public Store##Type##Operator {                                         \
    293     Store##Type##NoWriteBarrier##Operator()                                    \
    294         : Store##Type##Operator(kNoWriteBarrier) {}                            \
    295   };                                                                           \
    296   struct Store##Type##MapWriteBarrier##Operator final                          \
    297       : public Store##Type##Operator {                                         \
    298     Store##Type##MapWriteBarrier##Operator()                                   \
    299         : Store##Type##Operator(kMapWriteBarrier) {}                           \
    300   };                                                                           \
    301   struct Store##Type##PointerWriteBarrier##Operator final                      \
    302       : public Store##Type##Operator {                                         \
    303     Store##Type##PointerWriteBarrier##Operator()                               \
    304         : Store##Type##Operator(kPointerWriteBarrier) {}                       \
    305   };                                                                           \
    306   struct Store##Type##FullWriteBarrier##Operator final                         \
    307       : public Store##Type##Operator {                                         \
    308     Store##Type##FullWriteBarrier##Operator()                                  \
    309         : Store##Type##Operator(kFullWriteBarrier) {}                          \
    310   };                                                                           \
    311   struct CheckedStore##Type##Operator final                                    \
    312       : public Operator1<CheckedStoreRepresentation> {                         \
    313     CheckedStore##Type##Operator()                                             \
    314         : Operator1<CheckedStoreRepresentation>(                               \
    315               IrOpcode::kCheckedStore, Operator::kNoRead | Operator::kNoThrow, \
    316               "CheckedStore", 4, 1, 1, 0, 1, 0, MachineRepresentation::Type) { \
    317     }                                                                          \
    318   };                                                                           \
    319   Store##Type##NoWriteBarrier##Operator kStore##Type##NoWriteBarrier;          \
    320   Store##Type##MapWriteBarrier##Operator kStore##Type##MapWriteBarrier;        \
    321   Store##Type##PointerWriteBarrier##Operator                                   \
    322       kStore##Type##PointerWriteBarrier;                                       \
    323   Store##Type##FullWriteBarrier##Operator kStore##Type##FullWriteBarrier;      \
    324   CheckedStore##Type##Operator kCheckedStore##Type;
    325   MACHINE_REPRESENTATION_LIST(STORE)
    326 #undef STORE
    327 };
    328 
    329 
    330 static base::LazyInstance<MachineOperatorGlobalCache>::type kCache =
    331     LAZY_INSTANCE_INITIALIZER;
    332 
    333 
    334 MachineOperatorBuilder::MachineOperatorBuilder(Zone* zone,
    335                                                MachineRepresentation word,
    336                                                Flags flags)
    337     : cache_(kCache.Get()), word_(word), flags_(flags) {
    338   DCHECK(word == MachineRepresentation::kWord32 ||
    339          word == MachineRepresentation::kWord64);
    340 }
    341 
    342 
    343 #define PURE(Name, properties, value_input_count, control_input_count, \
    344              output_count)                                             \
    345   const Operator* MachineOperatorBuilder::Name() { return &cache_.k##Name; }
    346 PURE_OP_LIST(PURE)
    347 #undef PURE
    348 
    349 #define PURE(Name, properties, value_input_count, control_input_count,     \
    350              output_count)                                                 \
    351   const OptionalOperator MachineOperatorBuilder::Name() {                  \
    352     return OptionalOperator(flags_ & k##Name ? &cache_.k##Name : nullptr); \
    353   }
    354 PURE_OPTIONAL_OP_LIST(PURE)
    355 #undef PURE
    356 
    357 
    358 const Operator* MachineOperatorBuilder::TruncateFloat64ToInt32(
    359     TruncationMode mode) {
    360   switch (mode) {
    361     case TruncationMode::kJavaScript:
    362       return &cache_.kTruncateFloat64ToInt32JavaScript;
    363     case TruncationMode::kRoundToZero:
    364       return &cache_.kTruncateFloat64ToInt32RoundToZero;
    365   }
    366   UNREACHABLE();
    367   return nullptr;
    368 }
    369 
    370 
    371 const Operator* MachineOperatorBuilder::Load(LoadRepresentation rep) {
    372 #define LOAD(Type)                  \
    373   if (rep == MachineType::Type()) { \
    374     return &cache_.kLoad##Type;     \
    375   }
    376     MACHINE_TYPE_LIST(LOAD)
    377 #undef LOAD
    378   UNREACHABLE();
    379   return nullptr;
    380 }
    381 
    382 
    383 const Operator* MachineOperatorBuilder::Store(StoreRepresentation store_rep) {
    384   switch (store_rep.representation()) {
    385 #define STORE(kRep)                                         \
    386   case MachineRepresentation::kRep:                         \
    387     switch (store_rep.write_barrier_kind()) {               \
    388       case kNoWriteBarrier:                                 \
    389         return &cache_.k##Store##kRep##NoWriteBarrier;      \
    390       case kMapWriteBarrier:                                \
    391         return &cache_.k##Store##kRep##MapWriteBarrier;     \
    392       case kPointerWriteBarrier:                            \
    393         return &cache_.k##Store##kRep##PointerWriteBarrier; \
    394       case kFullWriteBarrier:                               \
    395         return &cache_.k##Store##kRep##FullWriteBarrier;    \
    396     }                                                       \
    397     break;
    398     MACHINE_REPRESENTATION_LIST(STORE)
    399 #undef STORE
    400     case MachineRepresentation::kBit:
    401     case MachineRepresentation::kNone:
    402       break;
    403   }
    404   UNREACHABLE();
    405   return nullptr;
    406 }
    407 
    408 
    409 const Operator* MachineOperatorBuilder::CheckedLoad(
    410     CheckedLoadRepresentation rep) {
    411 #define LOAD(Type)                     \
    412   if (rep == MachineType::Type()) {    \
    413     return &cache_.kCheckedLoad##Type; \
    414   }
    415     MACHINE_TYPE_LIST(LOAD)
    416 #undef LOAD
    417   UNREACHABLE();
    418   return nullptr;
    419 }
    420 
    421 
    422 const Operator* MachineOperatorBuilder::CheckedStore(
    423     CheckedStoreRepresentation rep) {
    424   switch (rep) {
    425 #define STORE(kRep)                 \
    426   case MachineRepresentation::kRep: \
    427     return &cache_.kCheckedStore##kRep;
    428     MACHINE_REPRESENTATION_LIST(STORE)
    429 #undef STORE
    430     case MachineRepresentation::kBit:
    431     case MachineRepresentation::kNone:
    432       break;
    433   }
    434   UNREACHABLE();
    435   return nullptr;
    436 }
    437 
    438 }  // namespace compiler
    439 }  // namespace internal
    440 }  // namespace v8
    441