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