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/simplified-operator-reducer.h"
      6 
      7 #include "src/compiler/js-graph.h"
      8 #include "src/compiler/machine-operator.h"
      9 #include "src/compiler/node-matchers.h"
     10 #include "src/compiler/operator-properties.h"
     11 #include "src/compiler/simplified-operator.h"
     12 #include "src/conversions-inl.h"
     13 #include "src/type-cache.h"
     14 
     15 namespace v8 {
     16 namespace internal {
     17 namespace compiler {
     18 
     19 namespace {
     20 
     21 Decision DecideObjectIsSmi(Node* const input) {
     22   NumberMatcher m(input);
     23   if (m.HasValue()) {
     24     return IsSmiDouble(m.Value()) ? Decision::kTrue : Decision::kFalse;
     25   }
     26   if (m.IsAllocate()) return Decision::kFalse;
     27   if (m.IsChangeBitToTagged()) return Decision::kFalse;
     28   if (m.IsChangeInt31ToTaggedSigned()) return Decision::kTrue;
     29   if (m.IsHeapConstant()) return Decision::kFalse;
     30   return Decision::kUnknown;
     31 }
     32 
     33 }  // namespace
     34 
     35 SimplifiedOperatorReducer::SimplifiedOperatorReducer(Editor* editor,
     36                                                      JSGraph* jsgraph)
     37     : AdvancedReducer(editor),
     38       jsgraph_(jsgraph),
     39       type_cache_(TypeCache::Get()) {}
     40 
     41 SimplifiedOperatorReducer::~SimplifiedOperatorReducer() {}
     42 
     43 
     44 Reduction SimplifiedOperatorReducer::Reduce(Node* node) {
     45   switch (node->opcode()) {
     46     case IrOpcode::kBooleanNot: {
     47       HeapObjectMatcher m(node->InputAt(0));
     48       if (m.HasValue()) {
     49         return Replace(jsgraph()->BooleanConstant(!m.Value()->BooleanValue()));
     50       }
     51       if (m.IsBooleanNot()) return Replace(m.InputAt(0));
     52       break;
     53     }
     54     case IrOpcode::kChangeBitToTagged: {
     55       Int32Matcher m(node->InputAt(0));
     56       if (m.Is(0)) return Replace(jsgraph()->FalseConstant());
     57       if (m.Is(1)) return Replace(jsgraph()->TrueConstant());
     58       if (m.IsChangeTaggedToBit()) return Replace(m.InputAt(0));
     59       break;
     60     }
     61     case IrOpcode::kChangeTaggedToBit: {
     62       HeapObjectMatcher m(node->InputAt(0));
     63       if (m.HasValue()) return ReplaceInt32(m.Value()->BooleanValue());
     64       if (m.IsChangeBitToTagged()) return Replace(m.InputAt(0));
     65       break;
     66     }
     67     case IrOpcode::kChangeFloat64ToTagged: {
     68       Float64Matcher m(node->InputAt(0));
     69       if (m.HasValue()) return ReplaceNumber(m.Value());
     70       if (m.IsChangeTaggedToFloat64()) return Replace(m.node()->InputAt(0));
     71       break;
     72     }
     73     case IrOpcode::kChangeInt31ToTaggedSigned:
     74     case IrOpcode::kChangeInt32ToTagged: {
     75       Int32Matcher m(node->InputAt(0));
     76       if (m.HasValue()) return ReplaceNumber(m.Value());
     77       if (m.IsChangeTaggedToInt32() || m.IsChangeTaggedSignedToInt32()) {
     78         return Replace(m.InputAt(0));
     79       }
     80       break;
     81     }
     82     case IrOpcode::kChangeTaggedToFloat64:
     83     case IrOpcode::kTruncateTaggedToFloat64: {
     84       NumberMatcher m(node->InputAt(0));
     85       if (m.HasValue()) return ReplaceFloat64(m.Value());
     86       if (m.IsChangeFloat64ToTagged()) return Replace(m.node()->InputAt(0));
     87       if (m.IsChangeInt31ToTaggedSigned() || m.IsChangeInt32ToTagged()) {
     88         return Change(node, machine()->ChangeInt32ToFloat64(), m.InputAt(0));
     89       }
     90       if (m.IsChangeUint32ToTagged()) {
     91         return Change(node, machine()->ChangeUint32ToFloat64(), m.InputAt(0));
     92       }
     93       break;
     94     }
     95     case IrOpcode::kChangeTaggedToInt32: {
     96       NumberMatcher m(node->InputAt(0));
     97       if (m.HasValue()) return ReplaceInt32(DoubleToInt32(m.Value()));
     98       if (m.IsChangeFloat64ToTagged()) {
     99         return Change(node, machine()->ChangeFloat64ToInt32(), m.InputAt(0));
    100       }
    101       if (m.IsChangeInt31ToTaggedSigned() || m.IsChangeInt32ToTagged()) {
    102         return Replace(m.InputAt(0));
    103       }
    104       break;
    105     }
    106     case IrOpcode::kChangeTaggedToUint32: {
    107       NumberMatcher m(node->InputAt(0));
    108       if (m.HasValue()) return ReplaceUint32(DoubleToUint32(m.Value()));
    109       if (m.IsChangeFloat64ToTagged()) {
    110         return Change(node, machine()->ChangeFloat64ToUint32(), m.InputAt(0));
    111       }
    112       if (m.IsChangeUint32ToTagged()) return Replace(m.InputAt(0));
    113       break;
    114     }
    115     case IrOpcode::kChangeUint32ToTagged: {
    116       Uint32Matcher m(node->InputAt(0));
    117       if (m.HasValue()) return ReplaceNumber(FastUI2D(m.Value()));
    118       break;
    119     }
    120     case IrOpcode::kTruncateTaggedToWord32: {
    121       NumberMatcher m(node->InputAt(0));
    122       if (m.HasValue()) return ReplaceInt32(DoubleToInt32(m.Value()));
    123       if (m.IsChangeInt31ToTaggedSigned() || m.IsChangeInt32ToTagged() ||
    124           m.IsChangeUint32ToTagged()) {
    125         return Replace(m.InputAt(0));
    126       }
    127       if (m.IsChangeFloat64ToTagged()) {
    128         return Change(node, machine()->TruncateFloat64ToWord32(), m.InputAt(0));
    129       }
    130       break;
    131     }
    132     case IrOpcode::kCheckTaggedPointer: {
    133       Node* const input = node->InputAt(0);
    134       if (DecideObjectIsSmi(input) == Decision::kFalse) {
    135         ReplaceWithValue(node, input);
    136         return Replace(input);
    137       }
    138       break;
    139     }
    140     case IrOpcode::kCheckTaggedSigned: {
    141       Node* const input = node->InputAt(0);
    142       if (DecideObjectIsSmi(input) == Decision::kTrue) {
    143         ReplaceWithValue(node, input);
    144         return Replace(input);
    145       }
    146       break;
    147     }
    148     case IrOpcode::kObjectIsSmi: {
    149       Node* const input = node->InputAt(0);
    150       switch (DecideObjectIsSmi(input)) {
    151         case Decision::kTrue:
    152           return ReplaceBoolean(true);
    153         case Decision::kFalse:
    154           return ReplaceBoolean(false);
    155         case Decision::kUnknown:
    156           break;
    157       }
    158       break;
    159     }
    160     case IrOpcode::kNumberAbs: {
    161       NumberMatcher m(node->InputAt(0));
    162       if (m.HasValue()) return ReplaceNumber(std::fabs(m.Value()));
    163       break;
    164     }
    165     case IrOpcode::kNumberCeil:
    166     case IrOpcode::kNumberFloor:
    167     case IrOpcode::kNumberRound:
    168     case IrOpcode::kNumberTrunc: {
    169       Node* const input = NodeProperties::GetValueInput(node, 0);
    170       Type* const input_type = NodeProperties::GetType(input);
    171       if (input_type->Is(type_cache_.kIntegerOrMinusZeroOrNaN)) {
    172         return Replace(input);
    173       }
    174       break;
    175     }
    176     case IrOpcode::kReferenceEqual:
    177       return ReduceReferenceEqual(node);
    178     case IrOpcode::kTypeGuard:
    179       return ReduceTypeGuard(node);
    180     default:
    181       break;
    182   }
    183   return NoChange();
    184 }
    185 
    186 Reduction SimplifiedOperatorReducer::ReduceReferenceEqual(Node* node) {
    187   DCHECK_EQ(IrOpcode::kReferenceEqual, node->opcode());
    188   Node* const left = NodeProperties::GetValueInput(node, 0);
    189   Node* const right = NodeProperties::GetValueInput(node, 1);
    190   HeapObjectMatcher match_left(left);
    191   HeapObjectMatcher match_right(right);
    192   if (match_left.HasValue() && match_right.HasValue()) {
    193     if (match_left.Value().is_identical_to(match_right.Value())) {
    194       return Replace(jsgraph()->TrueConstant());
    195     } else {
    196       return Replace(jsgraph()->FalseConstant());
    197     }
    198   }
    199   return NoChange();
    200 }
    201 
    202 Reduction SimplifiedOperatorReducer::ReduceTypeGuard(Node* node) {
    203   DCHECK_EQ(IrOpcode::kTypeGuard, node->opcode());
    204   Node* const input = NodeProperties::GetValueInput(node, 0);
    205   Type* const input_type = NodeProperties::GetTypeOrAny(input);
    206   Type* const guard_type = TypeOf(node->op());
    207   if (input_type->Is(guard_type)) return Replace(input);
    208   return NoChange();
    209 }
    210 
    211 Reduction SimplifiedOperatorReducer::Change(Node* node, const Operator* op,
    212                                             Node* a) {
    213   DCHECK_EQ(node->InputCount(), OperatorProperties::GetTotalInputCount(op));
    214   DCHECK_LE(1, node->InputCount());
    215   node->ReplaceInput(0, a);
    216   NodeProperties::ChangeOp(node, op);
    217   return Changed(node);
    218 }
    219 
    220 Reduction SimplifiedOperatorReducer::ReplaceBoolean(bool value) {
    221   return Replace(jsgraph()->BooleanConstant(value));
    222 }
    223 
    224 Reduction SimplifiedOperatorReducer::ReplaceFloat64(double value) {
    225   return Replace(jsgraph()->Float64Constant(value));
    226 }
    227 
    228 
    229 Reduction SimplifiedOperatorReducer::ReplaceInt32(int32_t value) {
    230   return Replace(jsgraph()->Int32Constant(value));
    231 }
    232 
    233 
    234 Reduction SimplifiedOperatorReducer::ReplaceNumber(double value) {
    235   return Replace(jsgraph()->Constant(value));
    236 }
    237 
    238 
    239 Reduction SimplifiedOperatorReducer::ReplaceNumber(int32_t value) {
    240   return Replace(jsgraph()->Constant(value));
    241 }
    242 
    243 
    244 Graph* SimplifiedOperatorReducer::graph() const { return jsgraph()->graph(); }
    245 
    246 
    247 MachineOperatorBuilder* SimplifiedOperatorReducer::machine() const {
    248   return jsgraph()->machine();
    249 }
    250 
    251 }  // namespace compiler
    252 }  // namespace internal
    253 }  // namespace v8
    254