1 // Copyright 2018 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/type-narrowing-reducer.h"
6 
7 #include "src/compiler/js-graph.h"
8 
9 namespace v8 {
10 namespace internal {
11 namespace compiler {
12 
TypeNarrowingReducer(Editor * editor,JSGraph * jsgraph,JSHeapBroker * broker)13 TypeNarrowingReducer::TypeNarrowingReducer(Editor* editor, JSGraph* jsgraph,
14                                            JSHeapBroker* broker)
15     : AdvancedReducer(editor), jsgraph_(jsgraph), op_typer_(broker, zone()) {}
16 
17 TypeNarrowingReducer::~TypeNarrowingReducer() = default;
18 
Reduce(Node * node)19 Reduction TypeNarrowingReducer::Reduce(Node* node) {
20   DisallowHeapAccess no_heap_access;
21 
22   Type new_type = Type::Any();
23 
24   switch (node->opcode()) {
25     case IrOpcode::kNumberLessThan: {
26       // TODO(turbofan) Reuse the logic from typer.cc (by integrating relational
27       // comparisons with the operation typer).
28       Type left_type = NodeProperties::GetType(node->InputAt(0));
29       Type right_type = NodeProperties::GetType(node->InputAt(1));
30       if (left_type.Is(Type::PlainNumber()) &&
31           right_type.Is(Type::PlainNumber())) {
32         if (left_type.Max() < right_type.Min()) {
33           new_type = op_typer_.singleton_true();
34         } else if (left_type.Min() >= right_type.Max()) {
35           new_type = op_typer_.singleton_false();
36         }
37       }
38       break;
39     }
40 
41     case IrOpcode::kTypeGuard: {
42       new_type = op_typer_.TypeTypeGuard(
43           node->op(), NodeProperties::GetType(node->InputAt(0)));
44       break;
45     }
46 
47 #define DECLARE_CASE(Name)                                                \
48   case IrOpcode::k##Name: {                                               \
49     new_type = op_typer_.Name(NodeProperties::GetType(node->InputAt(0)),  \
50                               NodeProperties::GetType(node->InputAt(1))); \
51     break;                                                                \
52   }
53       SIMPLIFIED_NUMBER_BINOP_LIST(DECLARE_CASE)
54       DECLARE_CASE(SameValue)
55 #undef DECLARE_CASE
56 
57 #define DECLARE_CASE(Name)                                                \
58   case IrOpcode::k##Name: {                                               \
59     new_type = op_typer_.Name(NodeProperties::GetType(node->InputAt(0))); \
60     break;                                                                \
61   }
62       SIMPLIFIED_NUMBER_UNOP_LIST(DECLARE_CASE)
63       DECLARE_CASE(ToBoolean)
64 #undef DECLARE_CASE
65 
66     default:
67       return NoChange();
68   }
69 
70   Type original_type = NodeProperties::GetType(node);
71   Type restricted = Type::Intersect(new_type, original_type, zone());
72   if (!original_type.Is(restricted)) {
73     NodeProperties::SetType(node, restricted);
74     return Changed(node);
75   }
76   return NoChange();
77 }
78 
graph() const79 Graph* TypeNarrowingReducer::graph() const { return jsgraph()->graph(); }
80 
zone() const81 Zone* TypeNarrowingReducer::zone() const { return graph()->zone(); }
82 
83 }  // namespace compiler
84 }  // namespace internal
85 }  // namespace v8
86