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/compiler/type-cache.h"
     13 #include "src/conversions-inl.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), jsgraph_(jsgraph) {}
     38 
     39 SimplifiedOperatorReducer::~SimplifiedOperatorReducer() {}
     40 
     41 
     42 Reduction SimplifiedOperatorReducer::Reduce(Node* node) {
     43   switch (node->opcode()) {
     44     case IrOpcode::kBooleanNot: {
     45       HeapObjectMatcher m(node->InputAt(0));
     46       if (m.Is(factory()->true_value())) return ReplaceBoolean(false);
     47       if (m.Is(factory()->false_value())) return ReplaceBoolean(true);
     48       if (m.IsBooleanNot()) return Replace(m.InputAt(0));
     49       break;
     50     }
     51     case IrOpcode::kChangeBitToTagged: {
     52       Int32Matcher m(node->InputAt(0));
     53       if (m.Is(0)) return Replace(jsgraph()->FalseConstant());
     54       if (m.Is(1)) return Replace(jsgraph()->TrueConstant());
     55       if (m.IsChangeTaggedToBit()) return Replace(m.InputAt(0));
     56       break;
     57     }
     58     case IrOpcode::kChangeTaggedToBit: {
     59       HeapObjectMatcher m(node->InputAt(0));
     60       if (m.HasValue()) return ReplaceInt32(m.Value()->BooleanValue());
     61       if (m.IsChangeBitToTagged()) return Replace(m.InputAt(0));
     62       break;
     63     }
     64     case IrOpcode::kChangeFloat64ToTagged: {
     65       Float64Matcher m(node->InputAt(0));
     66       if (m.HasValue()) return ReplaceNumber(m.Value());
     67       if (m.IsChangeTaggedToFloat64()) return Replace(m.node()->InputAt(0));
     68       break;
     69     }
     70     case IrOpcode::kChangeInt31ToTaggedSigned:
     71     case IrOpcode::kChangeInt32ToTagged: {
     72       Int32Matcher m(node->InputAt(0));
     73       if (m.HasValue()) return ReplaceNumber(m.Value());
     74       if (m.IsChangeTaggedToInt32() || m.IsChangeTaggedSignedToInt32()) {
     75         return Replace(m.InputAt(0));
     76       }
     77       break;
     78     }
     79     case IrOpcode::kChangeTaggedToFloat64:
     80     case IrOpcode::kTruncateTaggedToFloat64: {
     81       NumberMatcher m(node->InputAt(0));
     82       if (m.HasValue()) return ReplaceFloat64(m.Value());
     83       if (m.IsChangeFloat64ToTagged() || m.IsChangeFloat64ToTaggedPointer()) {
     84         return Replace(m.node()->InputAt(0));
     85       }
     86       if (m.IsChangeInt31ToTaggedSigned() || m.IsChangeInt32ToTagged()) {
     87         return Change(node, machine()->ChangeInt32ToFloat64(), m.InputAt(0));
     88       }
     89       if (m.IsChangeUint32ToTagged()) {
     90         return Change(node, machine()->ChangeUint32ToFloat64(), m.InputAt(0));
     91       }
     92       break;
     93     }
     94     case IrOpcode::kChangeTaggedSignedToInt32:
     95     case IrOpcode::kChangeTaggedToInt32: {
     96       NumberMatcher m(node->InputAt(0));
     97       if (m.HasValue()) return ReplaceInt32(DoubleToInt32(m.Value()));
     98       if (m.IsChangeFloat64ToTagged() || m.IsChangeFloat64ToTaggedPointer()) {
     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() || m.IsChangeFloat64ToTaggedPointer()) {
    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() || m.IsChangeFloat64ToTaggedPointer()) {
    128         return Change(node, machine()->TruncateFloat64ToWord32(), m.InputAt(0));
    129       }
    130       break;
    131     }
    132     case IrOpcode::kCheckedFloat64ToInt32: {
    133       Float64Matcher m(node->InputAt(0));
    134       if (m.HasValue() && IsInt32Double(m.Value())) {
    135         Node* value = jsgraph()->Int32Constant(static_cast<int32_t>(m.Value()));
    136         ReplaceWithValue(node, value);
    137         return Replace(value);
    138       }
    139       break;
    140     }
    141     case IrOpcode::kCheckedTaggedToInt32:
    142     case IrOpcode::kCheckedTaggedSignedToInt32: {
    143       NodeMatcher m(node->InputAt(0));
    144       if (m.IsConvertTaggedHoleToUndefined()) {
    145         node->ReplaceInput(0, m.InputAt(0));
    146         return Changed(node);
    147       }
    148       break;
    149     }
    150     case IrOpcode::kCheckIf: {
    151       HeapObjectMatcher m(node->InputAt(0));
    152       if (m.Is(factory()->true_value())) {
    153         Node* const effect = NodeProperties::GetEffectInput(node);
    154         return Replace(effect);
    155       }
    156       break;
    157     }
    158     case IrOpcode::kCheckNumber: {
    159       NodeMatcher m(node->InputAt(0));
    160       if (m.IsConvertTaggedHoleToUndefined()) {
    161         node->ReplaceInput(0, m.InputAt(0));
    162         return Changed(node);
    163       }
    164       break;
    165     }
    166     case IrOpcode::kCheckHeapObject: {
    167       Node* const input = node->InputAt(0);
    168       if (DecideObjectIsSmi(input) == Decision::kFalse) {
    169         ReplaceWithValue(node, input);
    170         return Replace(input);
    171       }
    172       NodeMatcher m(input);
    173       if (m.IsCheckHeapObject()) {
    174         ReplaceWithValue(node, input);
    175         return Replace(input);
    176       }
    177       break;
    178     }
    179     case IrOpcode::kCheckSmi: {
    180       Node* const input = node->InputAt(0);
    181       if (DecideObjectIsSmi(input) == Decision::kTrue) {
    182         ReplaceWithValue(node, input);
    183         return Replace(input);
    184       }
    185       NodeMatcher m(input);
    186       if (m.IsCheckSmi()) {
    187         ReplaceWithValue(node, input);
    188         return Replace(input);
    189       } else if (m.IsConvertTaggedHoleToUndefined()) {
    190         node->ReplaceInput(0, m.InputAt(0));
    191         return Changed(node);
    192       }
    193       break;
    194     }
    195     case IrOpcode::kObjectIsSmi: {
    196       Node* const input = node->InputAt(0);
    197       switch (DecideObjectIsSmi(input)) {
    198         case Decision::kTrue:
    199           return ReplaceBoolean(true);
    200         case Decision::kFalse:
    201           return ReplaceBoolean(false);
    202         case Decision::kUnknown:
    203           break;
    204       }
    205       break;
    206     }
    207     case IrOpcode::kNumberAbs: {
    208       NumberMatcher m(node->InputAt(0));
    209       if (m.HasValue()) return ReplaceNumber(std::fabs(m.Value()));
    210       break;
    211     }
    212     case IrOpcode::kReferenceEqual: {
    213       HeapObjectBinopMatcher m(node);
    214       if (m.left().node() == m.right().node()) return ReplaceBoolean(true);
    215       break;
    216     }
    217     default:
    218       break;
    219   }
    220   return NoChange();
    221 }
    222 
    223 Reduction SimplifiedOperatorReducer::Change(Node* node, const Operator* op,
    224                                             Node* a) {
    225   DCHECK_EQ(node->InputCount(), OperatorProperties::GetTotalInputCount(op));
    226   DCHECK_LE(1, node->InputCount());
    227   node->ReplaceInput(0, a);
    228   NodeProperties::ChangeOp(node, op);
    229   return Changed(node);
    230 }
    231 
    232 Reduction SimplifiedOperatorReducer::ReplaceBoolean(bool value) {
    233   return Replace(jsgraph()->BooleanConstant(value));
    234 }
    235 
    236 Reduction SimplifiedOperatorReducer::ReplaceFloat64(double value) {
    237   return Replace(jsgraph()->Float64Constant(value));
    238 }
    239 
    240 
    241 Reduction SimplifiedOperatorReducer::ReplaceInt32(int32_t value) {
    242   return Replace(jsgraph()->Int32Constant(value));
    243 }
    244 
    245 
    246 Reduction SimplifiedOperatorReducer::ReplaceNumber(double value) {
    247   return Replace(jsgraph()->Constant(value));
    248 }
    249 
    250 
    251 Reduction SimplifiedOperatorReducer::ReplaceNumber(int32_t value) {
    252   return Replace(jsgraph()->Constant(value));
    253 }
    254 
    255 Factory* SimplifiedOperatorReducer::factory() const {
    256   return isolate()->factory();
    257 }
    258 
    259 Graph* SimplifiedOperatorReducer::graph() const { return jsgraph()->graph(); }
    260 
    261 Isolate* SimplifiedOperatorReducer::isolate() const {
    262   return jsgraph()->isolate();
    263 }
    264 
    265 MachineOperatorBuilder* SimplifiedOperatorReducer::machine() const {
    266   return jsgraph()->machine();
    267 }
    268 
    269 }  // namespace compiler
    270 }  // namespace internal
    271 }  // namespace v8
    272