Line data Source code
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 59918 : Decision DecideObjectIsSmi(Node* const input) {
22 : NumberMatcher m(input);
23 59918 : if (m.HasValue()) {
24 5834 : return IsSmiDouble(m.Value()) ? Decision::kTrue : Decision::kFalse;
25 : }
26 54084 : if (m.IsAllocate()) return Decision::kFalse;
27 54084 : if (m.IsChangeBitToTagged()) return Decision::kFalse;
28 54082 : if (m.IsChangeInt31ToTaggedSigned()) return Decision::kTrue;
29 54082 : if (m.IsHeapConstant()) return Decision::kFalse;
30 54070 : return Decision::kUnknown;
31 : }
32 :
33 : } // namespace
34 :
35 791484 : SimplifiedOperatorReducer::SimplifiedOperatorReducer(Editor* editor,
36 : JSGraph* jsgraph)
37 791484 : : AdvancedReducer(editor), jsgraph_(jsgraph) {}
38 :
39 1582956 : SimplifiedOperatorReducer::~SimplifiedOperatorReducer() {}
40 :
41 :
42 80701190 : Reduction SimplifiedOperatorReducer::Reduce(Node* node) {
43 80700835 : switch (node->opcode()) {
44 : case IrOpcode::kBooleanNot: {
45 : HeapObjectMatcher m(node->InputAt(0));
46 35677 : if (m.Is(factory()->true_value())) return ReplaceBoolean(false);
47 25709 : if (m.Is(factory()->false_value())) return ReplaceBoolean(true);
48 18415 : if (m.IsBooleanNot()) return Replace(m.InputAt(0));
49 16191 : break;
50 : }
51 : case IrOpcode::kChangeBitToTagged: {
52 : Int32Matcher m(node->InputAt(0));
53 18492 : if (m.Is(0)) return Replace(jsgraph()->FalseConstant());
54 18396 : if (m.Is(1)) return Replace(jsgraph()->TrueConstant());
55 18128 : if (m.IsChangeTaggedToBit()) return Replace(m.InputAt(0));
56 : break;
57 : }
58 : case IrOpcode::kChangeTaggedToBit: {
59 : HeapObjectMatcher m(node->InputAt(0));
60 235874 : if (m.HasValue()) return ReplaceInt32(m.Value()->BooleanValue());
61 235870 : if (m.IsChangeBitToTagged()) return Replace(m.InputAt(0));
62 : break;
63 : }
64 : case IrOpcode::kChangeFloat64ToTagged: {
65 : Float64Matcher m(node->InputAt(0));
66 79963 : if (m.HasValue()) return ReplaceNumber(m.Value());
67 75878 : 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 69986 : if (m.HasValue()) return ReplaceNumber(m.Value());
74 64369 : 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 65618 : if (m.HasValue()) return ReplaceFloat64(m.Value());
83 43133 : if (m.IsChangeFloat64ToTagged() || m.IsChangeFloat64ToTaggedPointer()) {
84 : return Replace(m.node()->InputAt(0));
85 : }
86 43101 : if (m.IsChangeInt31ToTaggedSigned() || m.IsChangeInt32ToTagged()) {
87 1 : return Change(node, machine()->ChangeInt32ToFloat64(), m.InputAt(0));
88 : }
89 43100 : if (m.IsChangeUint32ToTagged()) {
90 1 : 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 129040 : if (m.HasValue()) return ReplaceInt32(DoubleToInt32(m.Value()));
98 127372 : if (m.IsChangeFloat64ToTagged() || m.IsChangeFloat64ToTaggedPointer()) {
99 2 : return Change(node, machine()->ChangeFloat64ToInt32(), m.InputAt(0));
100 : }
101 127370 : 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 529 : if (m.HasValue()) return ReplaceUint32(DoubleToUint32(m.Value()));
109 495 : if (m.IsChangeFloat64ToTagged() || m.IsChangeFloat64ToTaggedPointer()) {
110 2 : return Change(node, machine()->ChangeFloat64ToUint32(), m.InputAt(0));
111 : }
112 493 : if (m.IsChangeUint32ToTagged()) return Replace(m.InputAt(0));
113 : break;
114 : }
115 : case IrOpcode::kChangeUint32ToTagged: {
116 : Uint32Matcher m(node->InputAt(0));
117 1296 : if (m.HasValue()) return ReplaceNumber(FastUI2D(m.Value()));
118 : break;
119 : }
120 : case IrOpcode::kTruncateTaggedToWord32: {
121 : NumberMatcher m(node->InputAt(0));
122 2232 : if (m.HasValue()) return ReplaceInt32(DoubleToInt32(m.Value()));
123 2124 : if (m.IsChangeInt31ToTaggedSigned() || m.IsChangeInt32ToTagged() ||
124 : m.IsChangeUint32ToTagged()) {
125 : return Replace(m.InputAt(0));
126 : }
127 2124 : if (m.IsChangeFloat64ToTagged() || m.IsChangeFloat64ToTaggedPointer()) {
128 2 : return Change(node, machine()->TruncateFloat64ToWord32(), m.InputAt(0));
129 : }
130 : break;
131 : }
132 : case IrOpcode::kCheckedFloat64ToInt32: {
133 : Float64Matcher m(node->InputAt(0));
134 15350 : if (m.HasValue() && IsInt32Double(m.Value())) {
135 212 : Node* value = jsgraph()->Int32Constant(static_cast<int32_t>(m.Value()));
136 5788 : 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 249229 : if (m.IsConvertTaggedHoleToUndefined()) {
145 76 : 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 97701 : if (m.Is(factory()->true_value())) {
153 859 : Node* const effect = NodeProperties::GetEffectInput(node);
154 859 : return Replace(effect);
155 : }
156 96842 : break;
157 : }
158 : case IrOpcode::kCheckNumber: {
159 : NodeMatcher m(node->InputAt(0));
160 1432 : if (m.IsConvertTaggedHoleToUndefined()) {
161 0 : 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 29576 : if (DecideObjectIsSmi(input) == Decision::kFalse) {
169 : ReplaceWithValue(node, input);
170 : return Replace(input);
171 : }
172 : NodeMatcher m(input);
173 29571 : 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 16550 : if (DecideObjectIsSmi(input) == Decision::kTrue) {
182 : ReplaceWithValue(node, input);
183 : return Replace(input);
184 : }
185 : NodeMatcher m(input);
186 10875 : if (m.IsCheckSmi()) {
187 : ReplaceWithValue(node, input);
188 : return Replace(input);
189 10874 : } else if (m.IsConvertTaggedHoleToUndefined()) {
190 50 : 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 13792 : 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 250 : if (m.HasValue()) return ReplaceNumber(std::fabs(m.Value()));
210 : break;
211 : }
212 : case IrOpcode::kReferenceEqual: {
213 220220 : HeapObjectBinopMatcher m(node);
214 220493 : if (m.left().node() == m.right().node()) return ReplaceBoolean(true);
215 219947 : break;
216 : }
217 : default:
218 : break;
219 : }
220 : return NoChange();
221 : }
222 :
223 0 : 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 8 : node->ReplaceInput(0, a);
228 8 : NodeProperties::ChangeOp(node, op);
229 0 : return Changed(node);
230 : }
231 :
232 7909 : Reduction SimplifiedOperatorReducer::ReplaceBoolean(bool value) {
233 7909 : return Replace(jsgraph()->BooleanConstant(value));
234 : }
235 :
236 22485 : Reduction SimplifiedOperatorReducer::ReplaceFloat64(double value) {
237 22485 : return Replace(jsgraph()->Float64Constant(value));
238 : }
239 :
240 :
241 1812 : Reduction SimplifiedOperatorReducer::ReplaceInt32(int32_t value) {
242 1812 : return Replace(jsgraph()->Int32Constant(value));
243 : }
244 :
245 :
246 4700 : Reduction SimplifiedOperatorReducer::ReplaceNumber(double value) {
247 4700 : return Replace(jsgraph()->Constant(value));
248 : }
249 :
250 :
251 5617 : Reduction SimplifiedOperatorReducer::ReplaceNumber(int32_t value) {
252 5617 : return Replace(jsgraph()->Constant(value));
253 : }
254 :
255 0 : Factory* SimplifiedOperatorReducer::factory() const {
256 0 : return isolate()->factory();
257 : }
258 :
259 0 : Graph* SimplifiedOperatorReducer::graph() const { return jsgraph()->graph(); }
260 :
261 149344 : Isolate* SimplifiedOperatorReducer::isolate() const {
262 149344 : return jsgraph()->isolate();
263 : }
264 :
265 8 : MachineOperatorBuilder* SimplifiedOperatorReducer::machine() const {
266 8 : return jsgraph()->machine();
267 : }
268 :
269 : } // namespace compiler
270 : } // namespace internal
271 : } // namespace v8
|