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/machine-operator-reducer.h"
6 :
7 : #include "src/base/bits.h"
8 : #include "src/base/division-by-constant.h"
9 : #include "src/base/ieee754.h"
10 : #include "src/codegen.h"
11 : #include "src/compiler/diamond.h"
12 : #include "src/compiler/graph.h"
13 : #include "src/compiler/js-graph.h"
14 : #include "src/compiler/node-matchers.h"
15 : #include "src/objects-inl.h"
16 :
17 : namespace v8 {
18 : namespace internal {
19 : namespace compiler {
20 :
21 1649988 : MachineOperatorReducer::MachineOperatorReducer(JSGraph* jsgraph,
22 : bool allow_signalling_nan)
23 1649988 : : jsgraph_(jsgraph), allow_signalling_nan_(allow_signalling_nan) {}
24 :
25 3299828 : MachineOperatorReducer::~MachineOperatorReducer() {}
26 :
27 :
28 93389 : Node* MachineOperatorReducer::Float32Constant(volatile float value) {
29 280167 : return graph()->NewNode(common()->Float32Constant(value));
30 : }
31 :
32 :
33 112648 : Node* MachineOperatorReducer::Float64Constant(volatile double value) {
34 225296 : return jsgraph()->Float64Constant(value);
35 : }
36 :
37 :
38 598367 : Node* MachineOperatorReducer::Int32Constant(int32_t value) {
39 598367 : return jsgraph()->Int32Constant(value);
40 : }
41 :
42 :
43 921633 : Node* MachineOperatorReducer::Int64Constant(int64_t value) {
44 1843268 : return graph()->NewNode(common()->Int64Constant(value));
45 : }
46 :
47 0 : Node* MachineOperatorReducer::Float64Mul(Node* lhs, Node* rhs) {
48 0 : return graph()->NewNode(machine()->Float64Mul(), lhs, rhs);
49 : }
50 :
51 0 : Node* MachineOperatorReducer::Float64PowHalf(Node* value) {
52 : value =
53 0 : graph()->NewNode(machine()->Float64Add(), Float64Constant(0.0), value);
54 : Diamond d(graph(), common(),
55 : graph()->NewNode(machine()->Float64LessThanOrEqual(), value,
56 : Float64Constant(-V8_INFINITY)),
57 0 : BranchHint::kFalse);
58 : return d.Phi(MachineRepresentation::kFloat64, Float64Constant(V8_INFINITY),
59 0 : graph()->NewNode(machine()->Float64Sqrt(), value));
60 : }
61 :
62 114257 : Node* MachineOperatorReducer::Word32And(Node* lhs, Node* rhs) {
63 114257 : Node* const node = graph()->NewNode(machine()->Word32And(), lhs, rhs);
64 114257 : Reduction const reduction = ReduceWord32And(node);
65 114257 : return reduction.Changed() ? reduction.replacement() : node;
66 : }
67 :
68 :
69 7638 : Node* MachineOperatorReducer::Word32Sar(Node* lhs, uint32_t rhs) {
70 7638 : if (rhs == 0) return lhs;
71 14826 : return graph()->NewNode(machine()->Word32Sar(), lhs, Uint32Constant(rhs));
72 : }
73 :
74 :
75 7936 : Node* MachineOperatorReducer::Word32Shr(Node* lhs, uint32_t rhs) {
76 7936 : if (rhs == 0) return lhs;
77 15116 : return graph()->NewNode(machine()->Word32Shr(), lhs, Uint32Constant(rhs));
78 : }
79 :
80 :
81 12 : Node* MachineOperatorReducer::Word32Equal(Node* lhs, Node* rhs) {
82 24 : return graph()->NewNode(machine()->Word32Equal(), lhs, rhs);
83 : }
84 :
85 :
86 8467 : Node* MachineOperatorReducer::Int32Add(Node* lhs, Node* rhs) {
87 8467 : Node* const node = graph()->NewNode(machine()->Int32Add(), lhs, rhs);
88 8467 : Reduction const reduction = ReduceInt32Add(node);
89 8467 : return reduction.Changed() ? reduction.replacement() : node;
90 : }
91 :
92 :
93 2537 : Node* MachineOperatorReducer::Int32Sub(Node* lhs, Node* rhs) {
94 2537 : Node* const node = graph()->NewNode(machine()->Int32Sub(), lhs, rhs);
95 2537 : Reduction const reduction = ReduceInt32Sub(node);
96 2537 : return reduction.Changed() ? reduction.replacement() : node;
97 : }
98 :
99 :
100 3914 : Node* MachineOperatorReducer::Int32Mul(Node* lhs, Node* rhs) {
101 7828 : return graph()->NewNode(machine()->Int32Mul(), lhs, rhs);
102 : }
103 :
104 :
105 5869 : Node* MachineOperatorReducer::Int32Div(Node* dividend, int32_t divisor) {
106 : DCHECK_NE(0, divisor);
107 : DCHECK_NE(std::numeric_limits<int32_t>::min(), divisor);
108 : base::MagicNumbersForDivision<uint32_t> const mag =
109 5869 : base::SignedDivisionByConstant(bit_cast<uint32_t>(divisor));
110 : Node* quotient = graph()->NewNode(machine()->Int32MulHigh(), dividend,
111 5870 : Uint32Constant(mag.multiplier));
112 11740 : if (divisor > 0 && bit_cast<int32_t>(mag.multiplier) < 0) {
113 1567 : quotient = Int32Add(quotient, dividend);
114 4303 : } else if (divisor < 0 && bit_cast<int32_t>(mag.multiplier) > 0) {
115 0 : quotient = Int32Sub(quotient, dividend);
116 : }
117 5870 : return Int32Add(Word32Sar(quotient, mag.shift), Word32Shr(dividend, 31));
118 : }
119 :
120 :
121 518 : Node* MachineOperatorReducer::Uint32Div(Node* dividend, uint32_t divisor) {
122 : DCHECK_LT(0u, divisor);
123 : // If the divisor is even, we can avoid using the expensive fixup by shifting
124 : // the dividend upfront.
125 : unsigned const shift = base::bits::CountTrailingZeros32(divisor);
126 518 : dividend = Word32Shr(dividend, shift);
127 518 : divisor >>= shift;
128 : // Compute the magic number for the (shifted) divisor.
129 : base::MagicNumbersForDivision<uint32_t> const mag =
130 518 : base::UnsignedDivisionByConstant(divisor, shift);
131 : Node* quotient = graph()->NewNode(machine()->Uint32MulHigh(), dividend,
132 1036 : Uint32Constant(mag.multiplier));
133 518 : if (mag.add) {
134 : DCHECK_LE(1u, mag.shift);
135 : quotient = Word32Shr(
136 : Int32Add(Word32Shr(Int32Sub(dividend, quotient), 1), quotient),
137 57 : mag.shift - 1);
138 : } else {
139 461 : quotient = Word32Shr(quotient, mag.shift);
140 : }
141 518 : return quotient;
142 : }
143 :
144 :
145 : // Perform constant folding and strength reduction on machine operators.
146 89472453 : Reduction MachineOperatorReducer::Reduce(Node* node) {
147 89472453 : switch (node->opcode()) {
148 : case IrOpcode::kProjection:
149 227643 : return ReduceProjection(ProjectionIndexOf(node->op()), node->InputAt(0));
150 : case IrOpcode::kWord32And:
151 402081 : return ReduceWord32And(node);
152 : case IrOpcode::kWord32Or:
153 79843 : return ReduceWord32Or(node);
154 : case IrOpcode::kWord32Xor:
155 32122 : return ReduceWord32Xor(node);
156 : case IrOpcode::kWord32Shl:
157 55480 : return ReduceWord32Shl(node);
158 : case IrOpcode::kWord64Shl:
159 337056 : return ReduceWord64Shl(node);
160 : case IrOpcode::kWord32Shr:
161 45261 : return ReduceWord32Shr(node);
162 : case IrOpcode::kWord64Shr:
163 34789 : return ReduceWord64Shr(node);
164 : case IrOpcode::kWord32Sar:
165 48378 : return ReduceWord32Sar(node);
166 : case IrOpcode::kWord64Sar:
167 215313 : return ReduceWord64Sar(node);
168 : case IrOpcode::kWord32Ror: {
169 1900 : Int32BinopMatcher m(node);
170 3465 : if (m.right().Is(0)) return Replace(m.left().node()); // x ror 0 => x
171 1851 : if (m.IsFoldable()) { // K ror K => K
172 : return ReplaceInt32(
173 3032 : base::bits::RotateRight32(m.left().Value(), m.right().Value()));
174 : }
175 335 : break;
176 : }
177 : case IrOpcode::kWord32Equal: {
178 487139 : Int32BinopMatcher m(node);
179 487139 : if (m.IsFoldable()) { // K == K => K
180 78768 : return ReplaceBool(m.left().Value() == m.right().Value());
181 : }
182 450870 : if (m.left().IsInt32Sub() && m.right().Is(0)) { // x - y == 0 => x == y
183 1008 : Int32BinopMatcher msub(m.left().node());
184 1008 : node->ReplaceInput(0, msub.left().node());
185 1008 : node->ReplaceInput(1, msub.right().node());
186 : return Changed(node);
187 : }
188 : // TODO(turbofan): fold HeapConstant, ExternalReference, pointer compares
189 448802 : if (m.LeftEqualsRight()) return ReplaceBool(true); // x == x => true
190 445700 : break;
191 : }
192 : case IrOpcode::kWord64Equal: {
193 1449882 : Int64BinopMatcher m(node);
194 1449881 : if (m.IsFoldable()) { // K == K => K
195 5947 : return ReplaceBool(m.left().Value() == m.right().Value());
196 : }
197 1449739 : if (m.left().IsInt64Sub() && m.right().Is(0)) { // x - y == 0 => x == y
198 0 : Int64BinopMatcher msub(m.left().node());
199 0 : node->ReplaceInput(0, msub.left().node());
200 0 : node->ReplaceInput(1, msub.right().node());
201 : return Changed(node);
202 : }
203 : // TODO(turbofan): fold HeapConstant, ExternalReference, pointer compares
204 1449739 : if (m.LeftEqualsRight()) return ReplaceBool(true); // x == x => true
205 1444076 : break;
206 : }
207 : case IrOpcode::kInt32Add:
208 390775 : return ReduceInt32Add(node);
209 : case IrOpcode::kInt64Add:
210 738282 : return ReduceInt64Add(node);
211 : case IrOpcode::kInt32Sub:
212 75404 : return ReduceInt32Sub(node);
213 : case IrOpcode::kInt64Sub:
214 156718 : return ReduceInt64Sub(node);
215 : case IrOpcode::kInt32Mul: {
216 35753 : Int32BinopMatcher m(node);
217 57550 : if (m.right().Is(0)) return Replace(m.right().node()); // x * 0 => 0
218 35292 : if (m.right().Is(1)) return Replace(m.left().node()); // x * 1 => x
219 34653 : if (m.IsFoldable()) { // K * K => K
220 19844 : return ReplaceInt32(m.left().Value() * m.right().Value());
221 : }
222 14809 : if (m.right().Is(-1)) { // x * -1 => 0 - x
223 117 : node->ReplaceInput(0, Int32Constant(0));
224 117 : node->ReplaceInput(1, m.left().node());
225 117 : NodeProperties::ChangeOp(node, machine()->Int32Sub());
226 : return Changed(node);
227 : }
228 14692 : if (m.right().IsPowerOf2()) { // x * 2^n => x << n
229 1468 : node->ReplaceInput(1, Int32Constant(WhichPowerOf2(m.right().Value())));
230 734 : NodeProperties::ChangeOp(node, machine()->Word32Shl());
231 734 : Reduction reduction = ReduceWord32Shl(node);
232 734 : return reduction.Changed() ? reduction : Changed(node);
233 : }
234 13958 : break;
235 : }
236 : case IrOpcode::kInt32MulWithOverflow: {
237 7361 : Int32BinopMatcher m(node);
238 7361 : if (m.right().Is(2)) {
239 206 : node->ReplaceInput(1, m.left().node());
240 206 : NodeProperties::ChangeOp(node, machine()->Int32AddWithOverflow());
241 3448 : return Changed(node);
242 : }
243 7155 : if (m.right().Is(-1)) {
244 3242 : node->ReplaceInput(0, Int32Constant(0));
245 3242 : node->ReplaceInput(1, m.left().node());
246 3242 : NodeProperties::ChangeOp(node, machine()->Int32SubWithOverflow());
247 : return Changed(node);
248 : }
249 3913 : break;
250 : }
251 : case IrOpcode::kInt32Div:
252 23902 : return ReduceInt32Div(node);
253 : case IrOpcode::kUint32Div:
254 23216 : return ReduceUint32Div(node);
255 : case IrOpcode::kInt32Mod:
256 35682 : return ReduceInt32Mod(node);
257 : case IrOpcode::kUint32Mod:
258 23412 : return ReduceUint32Mod(node);
259 : case IrOpcode::kInt32LessThan: {
260 237947 : Int32BinopMatcher m(node);
261 237950 : if (m.IsFoldable()) { // K < K => K
262 48776 : return ReplaceBool(m.left().Value() < m.right().Value());
263 : }
264 213605 : if (m.LeftEqualsRight()) return ReplaceBool(false); // x < x => false
265 214707 : if (m.left().IsWord32Or() && m.right().Is(0)) {
266 : // (x | K) < 0 => true or (K | x) < 0 => true iff K < 0
267 1056 : Int32BinopMatcher mleftmatcher(m.left().node());
268 2112 : if (mleftmatcher.left().IsNegative() ||
269 : mleftmatcher.right().IsNegative()) {
270 71 : return ReplaceBool(true);
271 : }
272 : }
273 213519 : break;
274 : }
275 : case IrOpcode::kInt32LessThanOrEqual: {
276 27901 : Int32BinopMatcher m(node);
277 27901 : if (m.IsFoldable()) { // K <= K => K
278 44023 : return ReplaceBool(m.left().Value() <= m.right().Value());
279 : }
280 5893 : if (m.LeftEqualsRight()) return ReplaceBool(true); // x <= x => true
281 5886 : break;
282 : }
283 : case IrOpcode::kUint32LessThan: {
284 114933 : Uint32BinopMatcher m(node);
285 143574 : if (m.left().Is(kMaxUInt32)) return ReplaceBool(false); // M < x => false
286 114523 : if (m.right().Is(0)) return ReplaceBool(false); // x < 0 => false
287 113946 : if (m.IsFoldable()) { // K < K => K
288 25860 : return ReplaceBool(m.left().Value() < m.right().Value());
289 : }
290 88086 : if (m.LeftEqualsRight()) return ReplaceBool(false); // x < x => false
291 86593 : if (m.left().IsWord32Sar() && m.right().HasValue()) {
292 338 : Int32BinopMatcher mleft(m.left().node());
293 338 : if (mleft.right().HasValue()) {
294 : // (x >> K) < C => x < (C << K)
295 : // when C < (M >> K)
296 338 : const uint32_t c = m.right().Value();
297 338 : const uint32_t k = mleft.right().Value() & 0x1f;
298 338 : if (c < static_cast<uint32_t>(kMaxInt >> k)) {
299 301 : node->ReplaceInput(0, mleft.left().node());
300 602 : node->ReplaceInput(1, Uint32Constant(c << k));
301 301 : return Changed(node);
302 : }
303 : // TODO(turbofan): else the comparison is always true.
304 : }
305 : }
306 86292 : break;
307 : }
308 : case IrOpcode::kUint32LessThanOrEqual: {
309 64225 : Uint32BinopMatcher m(node);
310 85121 : if (m.left().Is(0)) return ReplaceBool(true); // 0 <= x => true
311 63661 : if (m.right().Is(kMaxUInt32)) return ReplaceBool(true); // x <= M => true
312 63283 : if (m.IsFoldable()) { // K <= K => K
313 19947 : return ReplaceBool(m.left().Value() <= m.right().Value());
314 : }
315 43336 : if (m.LeftEqualsRight()) return ReplaceBool(true); // x <= x => true
316 43329 : break;
317 : }
318 : case IrOpcode::kFloat32Sub: {
319 92693 : Float32BinopMatcher m(node);
320 186902 : if (allow_signalling_nan_ && m.right().Is(0) &&
321 1610 : (copysign(1.0, m.right().Value()) > 0)) {
322 92629 : return Replace(m.left().node()); // x - 0 => x
323 : }
324 91888 : if (m.right().IsNaN()) { // x - NaN => NaN
325 : // Do some calculation to make a signalling NaN quiet.
326 1633 : return ReplaceFloat32(m.right().Value() - m.right().Value());
327 : }
328 90255 : if (m.left().IsNaN()) { // NaN - x => NaN
329 : // Do some calculation to make a signalling NaN quiet.
330 1591 : return ReplaceFloat32(m.left().Value() - m.left().Value());
331 : }
332 88664 : if (m.IsFoldable()) { // L - R => (L - R)
333 88599 : return ReplaceFloat32(m.left().Value() - m.right().Value());
334 : }
335 65 : if (allow_signalling_nan_ && m.left().IsMinusZero()) {
336 : // -0.0 - round_down(-0.0 - R) => round_up(R)
337 1 : if (machine()->Float32RoundUp().IsSupported() &&
338 : m.right().IsFloat32RoundDown()) {
339 0 : if (m.right().InputAt(0)->opcode() == IrOpcode::kFloat32Sub) {
340 0 : Float32BinopMatcher mright0(m.right().InputAt(0));
341 0 : if (mright0.left().IsMinusZero()) {
342 : return Replace(graph()->NewNode(machine()->Float32RoundUp().op(),
343 0 : mright0.right().node()));
344 : }
345 : }
346 : }
347 : // -0.0 - R => -R
348 1 : node->RemoveInput(0);
349 1 : NodeProperties::ChangeOp(node, machine()->Float32Neg());
350 : return Changed(node);
351 : }
352 64 : break;
353 : }
354 : case IrOpcode::kFloat64Add: {
355 115379 : Float64BinopMatcher m(node);
356 115383 : if (m.right().IsNaN()) { // x + NaN => NaN
357 : // Do some calculation to make a signalling NaN quiet.
358 14903 : return ReplaceFloat64(m.right().Value() - m.right().Value());
359 : }
360 115305 : if (m.IsFoldable()) { // K + K => K
361 14747 : return ReplaceFloat64(m.left().Value() + m.right().Value());
362 : }
363 100558 : break;
364 : }
365 : case IrOpcode::kFloat64Sub: {
366 79670 : Float64BinopMatcher m(node);
367 160120 : if (allow_signalling_nan_ && m.right().Is(0) &&
368 873 : (Double(m.right().Value()).Sign() > 0)) {
369 36005 : return Replace(m.left().node()); // x - 0 => x
370 : }
371 79148 : if (m.right().IsNaN()) { // x - NaN => NaN
372 : // Do some calculation to make a signalling NaN quiet.
373 739 : return ReplaceFloat64(m.right().Value() - m.right().Value());
374 : }
375 78409 : if (m.left().IsNaN()) { // NaN - x => NaN
376 : // Do some calculation to make a signalling NaN quiet.
377 700 : return ReplaceFloat64(m.left().Value() - m.left().Value());
378 : }
379 77709 : if (m.IsFoldable()) { // L - R => (L - R)
380 24512 : return ReplaceFloat64(m.left().Value() - m.right().Value());
381 : }
382 53197 : if (allow_signalling_nan_ && m.left().IsMinusZero()) {
383 : // -0.0 - round_down(-0.0 - R) => round_up(R)
384 19065 : if (machine()->Float64RoundUp().IsSupported() &&
385 : m.right().IsFloat64RoundDown()) {
386 1314 : if (m.right().InputAt(0)->opcode() == IrOpcode::kFloat64Sub) {
387 0 : Float64BinopMatcher mright0(m.right().InputAt(0));
388 0 : if (mright0.left().IsMinusZero()) {
389 : return Replace(graph()->NewNode(machine()->Float64RoundUp().op(),
390 0 : mright0.right().node()));
391 : }
392 : }
393 : }
394 : // -0.0 - R => -R
395 9532 : node->RemoveInput(0);
396 9533 : NodeProperties::ChangeOp(node, machine()->Float64Neg());
397 : return Changed(node);
398 : }
399 43665 : break;
400 : }
401 : case IrOpcode::kFloat64Mul: {
402 43107 : Float64BinopMatcher m(node);
403 86147 : if (allow_signalling_nan_ && m.right().Is(1))
404 22718 : return Replace(m.left().node()); // x * 1.0 => x
405 32919 : if (m.right().Is(-1)) { // x * -1.0 => -0.0 - x
406 10214 : node->ReplaceInput(0, Float64Constant(-0.0));
407 10214 : node->ReplaceInput(1, m.left().node());
408 10213 : NodeProperties::ChangeOp(node, machine()->Float64Sub());
409 : return Changed(node);
410 : }
411 22706 : if (m.right().IsNaN()) { // x * NaN => NaN
412 : // Do some calculation to make a signalling NaN quiet.
413 42 : return ReplaceFloat64(m.right().Value() - m.right().Value());
414 : }
415 22664 : if (m.IsFoldable()) { // K * K => K
416 1989 : return ReplaceFloat64(m.left().Value() * m.right().Value());
417 : }
418 20675 : if (m.right().Is(2)) { // x * 2.0 => x + x
419 286 : node->ReplaceInput(1, m.left().node());
420 286 : NodeProperties::ChangeOp(node, machine()->Float64Add());
421 : return Changed(node);
422 : }
423 20389 : break;
424 : }
425 : case IrOpcode::kFloat64Div: {
426 34474 : Float64BinopMatcher m(node);
427 68853 : if (allow_signalling_nan_ && m.right().Is(1))
428 7451 : return Replace(m.left().node()); // x / 1.0 => x
429 : // TODO(ahaas): We could do x / 1.0 = x if we knew that x is not an sNaN.
430 33900 : if (m.right().IsNaN()) { // x / NaN => NaN
431 : // Do some calculation to make a signalling NaN quiet.
432 175 : return ReplaceFloat64(m.right().Value() - m.right().Value());
433 : }
434 33725 : if (m.left().IsNaN()) { // NaN / x => NaN
435 : // Do some calculation to make a signalling NaN quiet.
436 62 : return ReplaceFloat64(m.left().Value() - m.left().Value());
437 : }
438 33663 : if (m.IsFoldable()) { // K / K => K
439 3787 : return ReplaceFloat64(m.left().Value() / m.right().Value());
440 : }
441 59696 : if (allow_signalling_nan_ && m.right().Is(-1)) { // x / -1.0 => -x
442 65 : node->RemoveInput(1);
443 65 : NodeProperties::ChangeOp(node, machine()->Float64Neg());
444 : return Changed(node);
445 : }
446 29811 : if (m.right().IsNormal() && m.right().IsPositiveOrNegativePowerOf2()) {
447 : // All reciprocals of non-denormal powers of two can be represented
448 : // exactly, so division by power of two can be reduced to
449 : // multiplication by reciprocal, with the same result.
450 5576 : node->ReplaceInput(1, Float64Constant(1.0 / m.right().Value()));
451 2788 : NodeProperties::ChangeOp(node, machine()->Float64Mul());
452 : return Changed(node);
453 : }
454 27023 : break;
455 : }
456 : case IrOpcode::kFloat64Mod: {
457 2657 : Float64BinopMatcher m(node);
458 2657 : if (m.right().Is(0)) { // x % 0 => NaN
459 1248 : return ReplaceFloat64(std::numeric_limits<double>::quiet_NaN());
460 : }
461 2506 : if (m.right().IsNaN()) { // x % NaN => NaN
462 : return Replace(m.right().node());
463 : }
464 2469 : if (m.left().IsNaN()) { // NaN % x => NaN
465 : return Replace(m.left().node());
466 : }
467 2442 : if (m.IsFoldable()) { // K % K => K
468 1033 : return ReplaceFloat64(modulo(m.left().Value(), m.right().Value()));
469 : }
470 1409 : break;
471 : }
472 : case IrOpcode::kFloat64Acos: {
473 : Float64Matcher m(node->InputAt(0));
474 102 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::acos(m.Value()));
475 : break;
476 : }
477 : case IrOpcode::kFloat64Acosh: {
478 : Float64Matcher m(node->InputAt(0));
479 100 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::acosh(m.Value()));
480 : break;
481 : }
482 : case IrOpcode::kFloat64Asin: {
483 : Float64Matcher m(node->InputAt(0));
484 102 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::asin(m.Value()));
485 : break;
486 : }
487 : case IrOpcode::kFloat64Asinh: {
488 : Float64Matcher m(node->InputAt(0));
489 100 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::asinh(m.Value()));
490 : break;
491 : }
492 : case IrOpcode::kFloat64Atan: {
493 : Float64Matcher m(node->InputAt(0));
494 125 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::atan(m.Value()));
495 : break;
496 : }
497 : case IrOpcode::kFloat64Atanh: {
498 : Float64Matcher m(node->InputAt(0));
499 100 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::atanh(m.Value()));
500 : break;
501 : }
502 : case IrOpcode::kFloat64Atan2: {
503 10048 : Float64BinopMatcher m(node);
504 10048 : if (m.right().IsNaN()) {
505 10009 : return Replace(m.right().node());
506 : }
507 10047 : if (m.left().IsNaN()) {
508 : return Replace(m.left().node());
509 : }
510 10046 : if (m.IsFoldable()) {
511 : return ReplaceFloat64(
512 10007 : base::ieee754::atan2(m.left().Value(), m.right().Value()));
513 : }
514 39 : break;
515 : }
516 : case IrOpcode::kFloat64Cbrt: {
517 : Float64Matcher m(node->InputAt(0));
518 0 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::cbrt(m.Value()));
519 : break;
520 : }
521 : case IrOpcode::kFloat64Cos: {
522 : Float64Matcher m(node->InputAt(0));
523 386 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::cos(m.Value()));
524 : break;
525 : }
526 : case IrOpcode::kFloat64Cosh: {
527 : Float64Matcher m(node->InputAt(0));
528 118 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::cosh(m.Value()));
529 : break;
530 : }
531 : case IrOpcode::kFloat64Exp: {
532 : Float64Matcher m(node->InputAt(0));
533 149 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::exp(m.Value()));
534 : break;
535 : }
536 : case IrOpcode::kFloat64Expm1: {
537 : Float64Matcher m(node->InputAt(0));
538 0 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::expm1(m.Value()));
539 : break;
540 : }
541 : case IrOpcode::kFloat64Log: {
542 : Float64Matcher m(node->InputAt(0));
543 345 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::log(m.Value()));
544 : break;
545 : }
546 : case IrOpcode::kFloat64Log1p: {
547 : Float64Matcher m(node->InputAt(0));
548 100 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::log1p(m.Value()));
549 : break;
550 : }
551 : case IrOpcode::kFloat64Log10: {
552 : Float64Matcher m(node->InputAt(0));
553 0 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::log10(m.Value()));
554 : break;
555 : }
556 : case IrOpcode::kFloat64Log2: {
557 : Float64Matcher m(node->InputAt(0));
558 0 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::log2(m.Value()));
559 : break;
560 : }
561 : case IrOpcode::kFloat64Pow: {
562 10975 : Float64BinopMatcher m(node);
563 10975 : if (m.IsFoldable()) {
564 21698 : return ReplaceFloat64(Pow(m.left().Value(), m.right().Value()));
565 127 : } else if (m.right().Is(0.0)) { // x ** +-0.0 => 1.0
566 : return ReplaceFloat64(1.0);
567 125 : } else if (m.right().Is(-2.0)) { // x ** -2.0 => 1 / (x * x)
568 0 : node->ReplaceInput(0, Float64Constant(1.0));
569 0 : node->ReplaceInput(1, Float64Mul(m.left().node(), m.left().node()));
570 0 : NodeProperties::ChangeOp(node, machine()->Float64Div());
571 : return Changed(node);
572 125 : } else if (m.right().Is(2.0)) { // x ** 2.0 => x * x
573 0 : node->ReplaceInput(1, m.left().node());
574 0 : NodeProperties::ChangeOp(node, machine()->Float64Mul());
575 : return Changed(node);
576 125 : } else if (m.right().Is(-0.5)) {
577 : // x ** 0.5 => 1 / (if x <= -Infinity then Infinity else sqrt(0.0 + x))
578 0 : node->ReplaceInput(0, Float64Constant(1.0));
579 0 : node->ReplaceInput(1, Float64PowHalf(m.left().node()));
580 0 : NodeProperties::ChangeOp(node, machine()->Float64Div());
581 : return Changed(node);
582 125 : } else if (m.right().Is(0.5)) {
583 : // x ** 0.5 => if x <= -Infinity then Infinity else sqrt(0.0 + x)
584 0 : return Replace(Float64PowHalf(m.left().node()));
585 : }
586 125 : break;
587 : }
588 : case IrOpcode::kFloat64Sin: {
589 : Float64Matcher m(node->InputAt(0));
590 411 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::sin(m.Value()));
591 : break;
592 : }
593 : case IrOpcode::kFloat64Sinh: {
594 : Float64Matcher m(node->InputAt(0));
595 118 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::sinh(m.Value()));
596 : break;
597 : }
598 : case IrOpcode::kFloat64Tan: {
599 : Float64Matcher m(node->InputAt(0));
600 125 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::tan(m.Value()));
601 : break;
602 : }
603 : case IrOpcode::kFloat64Tanh: {
604 : Float64Matcher m(node->InputAt(0));
605 118 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::tanh(m.Value()));
606 : break;
607 : }
608 : case IrOpcode::kChangeFloat32ToFloat64: {
609 : Float32Matcher m(node->InputAt(0));
610 15707 : if (m.HasValue()) {
611 199 : if (!allow_signalling_nan_ && std::isnan(m.Value())) {
612 : // Do some calculation to make guarantee the value is a quiet NaN.
613 16 : return ReplaceFloat64(m.Value() + m.Value());
614 : }
615 183 : return ReplaceFloat64(m.Value());
616 : }
617 : break;
618 : }
619 : case IrOpcode::kChangeFloat64ToInt32: {
620 : Float64Matcher m(node->InputAt(0));
621 12956 : if (m.HasValue()) return ReplaceInt32(FastD2I(m.Value()));
622 8320 : if (m.IsChangeInt32ToFloat64()) return Replace(m.node()->InputAt(0));
623 : break;
624 : }
625 : case IrOpcode::kChangeFloat64ToUint32: {
626 : Float64Matcher m(node->InputAt(0));
627 608 : if (m.HasValue()) return ReplaceInt32(FastD2UI(m.Value()));
628 494 : if (m.IsChangeUint32ToFloat64()) return Replace(m.node()->InputAt(0));
629 : break;
630 : }
631 : case IrOpcode::kChangeInt32ToFloat64: {
632 : Int32Matcher m(node->InputAt(0));
633 193978 : if (m.HasValue()) return ReplaceFloat64(FastI2D(m.Value()));
634 : break;
635 : }
636 : case IrOpcode::kChangeInt32ToInt64: {
637 : Int32Matcher m(node->InputAt(0));
638 216931 : if (m.HasValue()) return ReplaceInt64(m.Value());
639 : break;
640 : }
641 : case IrOpcode::kChangeUint32ToFloat64: {
642 : Uint32Matcher m(node->InputAt(0));
643 2083 : if (m.HasValue()) return ReplaceFloat64(FastUI2D(m.Value()));
644 : break;
645 : }
646 : case IrOpcode::kChangeUint32ToUint64: {
647 : Uint32Matcher m(node->InputAt(0));
648 204313 : if (m.HasValue()) return ReplaceInt64(static_cast<uint64_t>(m.Value()));
649 : break;
650 : }
651 : case IrOpcode::kTruncateFloat64ToWord32: {
652 : Float64Matcher m(node->InputAt(0));
653 25881 : if (m.HasValue()) return ReplaceInt32(DoubleToInt32(m.Value()));
654 22336 : if (m.IsChangeInt32ToFloat64()) return Replace(m.node()->InputAt(0));
655 : return NoChange();
656 : }
657 : case IrOpcode::kTruncateInt64ToInt32: {
658 : Int64Matcher m(node->InputAt(0));
659 172241 : if (m.HasValue()) return ReplaceInt32(static_cast<int32_t>(m.Value()));
660 171468 : if (m.IsChangeInt32ToInt64()) return Replace(m.node()->InputAt(0));
661 : break;
662 : }
663 : case IrOpcode::kTruncateFloat64ToFloat32: {
664 : Float64Matcher m(node->InputAt(0));
665 7998 : if (m.HasValue()) {
666 875 : if (!allow_signalling_nan_ && std::isnan(m.Value())) {
667 : // Do some calculation to make guarantee the value is a quiet NaN.
668 16 : return ReplaceFloat32(DoubleToFloat32(m.Value() + m.Value()));
669 : }
670 : return ReplaceFloat32(DoubleToFloat32(m.Value()));
671 : }
672 7123 : if (allow_signalling_nan_ && m.IsChangeFloat32ToFloat64())
673 : return Replace(m.node()->InputAt(0));
674 : break;
675 : }
676 : case IrOpcode::kRoundFloat64ToInt32: {
677 : Float64Matcher m(node->InputAt(0));
678 55394 : if (m.HasValue()) return ReplaceInt32(static_cast<int32_t>(m.Value()));
679 55087 : if (m.IsChangeInt32ToFloat64()) return Replace(m.node()->InputAt(0));
680 : break;
681 : }
682 : case IrOpcode::kFloat64InsertLowWord32:
683 4800 : return ReduceFloat64InsertLowWord32(node);
684 : case IrOpcode::kFloat64InsertHighWord32:
685 4800 : return ReduceFloat64InsertHighWord32(node);
686 : case IrOpcode::kStore:
687 : case IrOpcode::kUnalignedStore:
688 : case IrOpcode::kCheckedStore:
689 1454432 : return ReduceStore(node);
690 : case IrOpcode::kFloat64Equal:
691 : case IrOpcode::kFloat64LessThan:
692 : case IrOpcode::kFloat64LessThanOrEqual:
693 191628 : return ReduceFloat64Compare(node);
694 : case IrOpcode::kFloat64RoundDown:
695 18064 : return ReduceFloat64RoundDown(node);
696 : default:
697 : break;
698 : }
699 : return NoChange();
700 : }
701 :
702 536046 : Reduction MachineOperatorReducer::ReduceInt32Add(Node* node) {
703 : DCHECK_EQ(IrOpcode::kInt32Add, node->opcode());
704 536046 : Int32BinopMatcher m(node);
705 536061 : if (m.right().Is(0)) return Replace(m.left().node()); // x + 0 => x
706 513189 : if (m.IsFoldable()) { // K + K => K
707 : return ReplaceUint32(bit_cast<uint32_t>(m.left().Value()) +
708 39734 : bit_cast<uint32_t>(m.right().Value()));
709 : }
710 473455 : if (m.left().IsInt32Sub()) {
711 1504 : Int32BinopMatcher mleft(m.left().node());
712 1504 : if (mleft.left().Is(0)) { // (0 - x) + y => y - x
713 12 : node->ReplaceInput(0, m.right().node());
714 12 : node->ReplaceInput(1, mleft.right().node());
715 12 : NodeProperties::ChangeOp(node, machine()->Int32Sub());
716 12 : Reduction const reduction = ReduceInt32Sub(node);
717 12 : return reduction.Changed() ? reduction : Changed(node);
718 : }
719 : }
720 473443 : if (m.right().IsInt32Sub()) {
721 732 : Int32BinopMatcher mright(m.right().node());
722 732 : if (mright.left().Is(0)) { // y + (0 - x) => y - x
723 50 : node->ReplaceInput(1, mright.right().node());
724 50 : NodeProperties::ChangeOp(node, machine()->Int32Sub());
725 50 : Reduction const reduction = ReduceInt32Sub(node);
726 50 : return reduction.Changed() ? reduction : Changed(node);
727 : }
728 : }
729 : return NoChange();
730 : }
731 :
732 852814 : Reduction MachineOperatorReducer::ReduceInt64Add(Node* node) {
733 : DCHECK_EQ(IrOpcode::kInt64Add, node->opcode());
734 852814 : Int64BinopMatcher m(node);
735 852815 : if (m.right().Is(0)) return Replace(m.left().node()); // x + 0 => 0
736 851723 : if (m.IsFoldable()) {
737 : return Replace(Uint64Constant(bit_cast<uint64_t>(m.left().Value()) +
738 205863 : bit_cast<uint64_t>(m.right().Value())));
739 : }
740 : return NoChange();
741 : }
742 :
743 78061 : Reduction MachineOperatorReducer::ReduceInt32Sub(Node* node) {
744 : DCHECK_EQ(IrOpcode::kInt32Sub, node->opcode());
745 78061 : Int32BinopMatcher m(node);
746 78081 : if (m.right().Is(0)) return Replace(m.left().node()); // x - 0 => x
747 77284 : if (m.IsFoldable()) { // K - K => K
748 29301 : return ReplaceInt32(static_cast<uint32_t>(m.left().Value()) -
749 29301 : static_cast<uint32_t>(m.right().Value()));
750 : }
751 47983 : if (m.LeftEqualsRight()) return ReplaceInt32(0); // x - x => 0
752 47981 : if (m.right().HasValue()) { // x - K => x + -K
753 50064 : node->ReplaceInput(1, Int32Constant(-m.right().Value()));
754 25030 : NodeProperties::ChangeOp(node, machine()->Int32Add());
755 25032 : Reduction const reduction = ReduceInt32Add(node);
756 25016 : return reduction.Changed() ? reduction : Changed(node);
757 : }
758 : return NoChange();
759 : }
760 :
761 156717 : Reduction MachineOperatorReducer::ReduceInt64Sub(Node* node) {
762 : DCHECK_EQ(IrOpcode::kInt64Sub, node->opcode());
763 156717 : Int64BinopMatcher m(node);
764 156717 : if (m.right().Is(0)) return Replace(m.left().node()); // x - 0 => x
765 155632 : if (m.IsFoldable()) { // K - K => K
766 : return Replace(Uint64Constant(bit_cast<uint64_t>(m.left().Value()) -
767 40454 : bit_cast<uint64_t>(m.right().Value())));
768 : }
769 115178 : if (m.LeftEqualsRight()) return Replace(Int64Constant(0)); // x - x => 0
770 115171 : if (m.right().HasValue()) { // x - K => x + -K
771 114533 : node->ReplaceInput(1, Int64Constant(-m.right().Value()));
772 114532 : NodeProperties::ChangeOp(node, machine()->Int64Add());
773 114532 : Reduction const reduction = ReduceInt64Add(node);
774 114532 : return reduction.Changed() ? reduction : Changed(node);
775 : }
776 : return NoChange();
777 : }
778 :
779 23901 : Reduction MachineOperatorReducer::ReduceInt32Div(Node* node) {
780 23901 : Int32BinopMatcher m(node);
781 23902 : if (m.left().Is(0)) return Replace(m.left().node()); // 0 / x => 0
782 23525 : if (m.right().Is(0)) return Replace(m.right().node()); // x / 0 => 0
783 23517 : if (m.right().Is(1)) return Replace(m.left().node()); // x / 1 => x
784 23078 : if (m.IsFoldable()) { // K / K => K
785 : return ReplaceInt32(
786 19353 : base::bits::SignedDiv32(m.left().Value(), m.right().Value()));
787 : }
788 3725 : if (m.LeftEqualsRight()) { // x / x => x != 0
789 : Node* const zero = Int32Constant(0);
790 5 : return Replace(Word32Equal(Word32Equal(m.left().node(), zero), zero));
791 : }
792 3720 : if (m.right().Is(-1)) { // x / -1 => 0 - x
793 41 : node->ReplaceInput(0, Int32Constant(0));
794 41 : node->ReplaceInput(1, m.left().node());
795 41 : node->TrimInputCount(2);
796 41 : NodeProperties::ChangeOp(node, machine()->Int32Sub());
797 : return Changed(node);
798 : }
799 3679 : if (m.right().HasValue()) {
800 3306 : int32_t const divisor = m.right().Value();
801 : Node* const dividend = m.left().node();
802 : Node* quotient = dividend;
803 6612 : if (base::bits::IsPowerOfTwo32(Abs(divisor))) {
804 973 : uint32_t const shift = WhichPowerOf2Abs(divisor);
805 : DCHECK_NE(0u, shift);
806 973 : if (shift > 1) {
807 795 : quotient = Word32Sar(quotient, 31);
808 : }
809 973 : quotient = Int32Add(Word32Shr(quotient, 32u - shift), dividend);
810 973 : quotient = Word32Sar(quotient, shift);
811 : } else {
812 2333 : quotient = Int32Div(quotient, Abs(divisor));
813 : }
814 3306 : if (divisor < 0) {
815 1462 : node->ReplaceInput(0, Int32Constant(0));
816 1462 : node->ReplaceInput(1, quotient);
817 1462 : node->TrimInputCount(2);
818 1462 : NodeProperties::ChangeOp(node, machine()->Int32Sub());
819 : return Changed(node);
820 : }
821 : return Replace(quotient);
822 : }
823 : return NoChange();
824 : }
825 :
826 :
827 23216 : Reduction MachineOperatorReducer::ReduceUint32Div(Node* node) {
828 23216 : Uint32BinopMatcher m(node);
829 23216 : if (m.left().Is(0)) return Replace(m.left().node()); // 0 / x => 0
830 22770 : if (m.right().Is(0)) return Replace(m.right().node()); // x / 0 => 0
831 22707 : if (m.right().Is(1)) return Replace(m.left().node()); // x / 1 => x
832 22266 : if (m.IsFoldable()) { // K / K => K
833 : return ReplaceUint32(
834 21516 : base::bits::UnsignedDiv32(m.left().Value(), m.right().Value()));
835 : }
836 750 : if (m.LeftEqualsRight()) { // x / x => x != 0
837 : Node* const zero = Int32Constant(0);
838 1 : return Replace(Word32Equal(Word32Equal(m.left().node(), zero), zero));
839 : }
840 749 : if (m.right().HasValue()) {
841 : Node* const dividend = m.left().node();
842 513 : uint32_t const divisor = m.right().Value();
843 513 : if (base::bits::IsPowerOfTwo32(divisor)) { // x / 2^n => x >> n
844 744 : node->ReplaceInput(1, Uint32Constant(WhichPowerOf2(m.right().Value())));
845 372 : node->TrimInputCount(2);
846 372 : NodeProperties::ChangeOp(node, machine()->Word32Shr());
847 : return Changed(node);
848 : } else {
849 141 : return Replace(Uint32Div(dividend, divisor));
850 : }
851 : }
852 : return NoChange();
853 : }
854 :
855 :
856 35682 : Reduction MachineOperatorReducer::ReduceInt32Mod(Node* node) {
857 35682 : Int32BinopMatcher m(node);
858 35682 : if (m.left().Is(0)) return Replace(m.left().node()); // 0 % x => 0
859 35193 : if (m.right().Is(0)) return Replace(m.right().node()); // x % 0 => 0
860 35093 : if (m.right().Is(1)) return ReplaceInt32(0); // x % 1 => 0
861 34698 : if (m.right().Is(-1)) return ReplaceInt32(0); // x % -1 => 0
862 34326 : if (m.LeftEqualsRight()) return ReplaceInt32(0); // x % x => 0
863 34308 : if (m.IsFoldable()) { // K % K => K
864 : return ReplaceInt32(
865 28810 : base::bits::SignedMod32(m.left().Value(), m.right().Value()));
866 : }
867 5498 : if (m.right().HasValue()) {
868 : Node* const dividend = m.left().node();
869 4777 : int32_t const divisor = Abs(m.right().Value());
870 9554 : if (base::bits::IsPowerOfTwo32(divisor)) {
871 1240 : uint32_t const mask = divisor - 1;
872 : Node* const zero = Int32Constant(0);
873 : Diamond d(graph(), common(),
874 : graph()->NewNode(machine()->Int32LessThan(), dividend, zero),
875 2480 : BranchHint::kFalse);
876 : return Replace(
877 : d.Phi(MachineRepresentation::kWord32,
878 : Int32Sub(zero, Word32And(Int32Sub(zero, dividend), mask)),
879 1240 : Word32And(dividend, mask)));
880 : } else {
881 3537 : Node* quotient = Int32Div(dividend, divisor);
882 : DCHECK_EQ(dividend, node->InputAt(0));
883 3537 : node->ReplaceInput(1, Int32Mul(quotient, Int32Constant(divisor)));
884 3537 : node->TrimInputCount(2);
885 3537 : NodeProperties::ChangeOp(node, machine()->Int32Sub());
886 : }
887 : return Changed(node);
888 : }
889 : return NoChange();
890 : }
891 :
892 :
893 23412 : Reduction MachineOperatorReducer::ReduceUint32Mod(Node* node) {
894 23412 : Uint32BinopMatcher m(node);
895 23412 : if (m.left().Is(0)) return Replace(m.left().node()); // 0 % x => 0
896 22941 : if (m.right().Is(0)) return Replace(m.right().node()); // x % 0 => 0
897 22878 : if (m.right().Is(1)) return ReplaceUint32(0); // x % 1 => 0
898 22451 : if (m.LeftEqualsRight()) return ReplaceInt32(0); // x % x => 0
899 22449 : if (m.IsFoldable()) { // K % K => K
900 : return ReplaceUint32(
901 21526 : base::bits::UnsignedMod32(m.left().Value(), m.right().Value()));
902 : }
903 923 : if (m.right().HasValue()) {
904 : Node* const dividend = m.left().node();
905 729 : uint32_t const divisor = m.right().Value();
906 729 : if (base::bits::IsPowerOfTwo32(divisor)) { // x % 2^n => x & 2^n-1
907 704 : node->ReplaceInput(1, Uint32Constant(m.right().Value() - 1));
908 352 : node->TrimInputCount(2);
909 352 : NodeProperties::ChangeOp(node, machine()->Word32And());
910 : } else {
911 377 : Node* quotient = Uint32Div(dividend, divisor);
912 : DCHECK_EQ(dividend, node->InputAt(0));
913 377 : node->ReplaceInput(1, Int32Mul(quotient, Uint32Constant(divisor)));
914 377 : node->TrimInputCount(2);
915 377 : NodeProperties::ChangeOp(node, machine()->Int32Sub());
916 : }
917 : return Changed(node);
918 : }
919 : return NoChange();
920 : }
921 :
922 :
923 1454431 : Reduction MachineOperatorReducer::ReduceStore(Node* node) {
924 : NodeMatcher nm(node);
925 : MachineRepresentation rep;
926 : int value_input;
927 1454431 : if (nm.IsCheckedStore()) {
928 64147 : rep = CheckedStoreRepresentationOf(node->op());
929 : value_input = 3;
930 1390284 : } else if (nm.IsStore()) {
931 1390284 : rep = StoreRepresentationOf(node->op()).representation();
932 : value_input = 2;
933 : } else {
934 : DCHECK(nm.IsUnalignedStore());
935 0 : rep = UnalignedStoreRepresentationOf(node->op());
936 : value_input = 2;
937 : }
938 :
939 1454431 : Node* const value = node->InputAt(value_input);
940 :
941 1454431 : switch (value->opcode()) {
942 : case IrOpcode::kWord32And: {
943 2021 : Uint32BinopMatcher m(value);
944 4628 : if (m.right().HasValue() && ((rep == MachineRepresentation::kWord8 &&
945 1570 : (m.right().Value() & 0xff) == 0xff) ||
946 311 : (rep == MachineRepresentation::kWord16 &&
947 311 : (m.right().Value() & 0xffff) == 0xffff))) {
948 720 : node->ReplaceInput(value_input, m.left().node());
949 720 : return Changed(node);
950 : }
951 1301 : break;
952 : }
953 : case IrOpcode::kWord32Sar: {
954 438 : Int32BinopMatcher m(value);
955 1047 : if (m.left().IsWord32Shl() && ((rep == MachineRepresentation::kWord8 &&
956 267 : m.right().IsInRange(1, 24)) ||
957 267 : (rep == MachineRepresentation::kWord16 &&
958 : m.right().IsInRange(1, 16)))) {
959 438 : Int32BinopMatcher mleft(m.left().node());
960 438 : if (mleft.right().Is(m.right().Value())) {
961 438 : node->ReplaceInput(value_input, mleft.left().node());
962 438 : return Changed(node);
963 : }
964 : }
965 0 : break;
966 : }
967 : default:
968 : break;
969 : }
970 : return NoChange();
971 : }
972 :
973 :
974 227643 : Reduction MachineOperatorReducer::ReduceProjection(size_t index, Node* node) {
975 227643 : switch (node->opcode()) {
976 : case IrOpcode::kInt32AddWithOverflow: {
977 : DCHECK(index == 0 || index == 1);
978 111786 : Int32BinopMatcher m(node);
979 111786 : if (m.IsFoldable()) {
980 : int32_t val;
981 : bool ovf = base::bits::SignedAddOverflow32(m.left().Value(),
982 20038 : m.right().Value(), &val);
983 20038 : return ReplaceInt32(index == 0 ? val : ovf);
984 : }
985 91748 : if (m.right().Is(0)) {
986 32 : return Replace(index == 0 ? m.left().node() : m.right().node());
987 : }
988 91716 : break;
989 : }
990 : case IrOpcode::kInt32SubWithOverflow: {
991 : DCHECK(index == 0 || index == 1);
992 74836 : Int32BinopMatcher m(node);
993 74836 : if (m.IsFoldable()) {
994 : int32_t val;
995 : bool ovf = base::bits::SignedSubOverflow32(m.left().Value(),
996 20024 : m.right().Value(), &val);
997 20024 : return ReplaceInt32(index == 0 ? val : ovf);
998 : }
999 54812 : if (m.right().Is(0)) {
1000 2 : return Replace(index == 0 ? m.left().node() : m.right().node());
1001 : }
1002 54810 : break;
1003 : }
1004 : case IrOpcode::kInt32MulWithOverflow: {
1005 : DCHECK(index == 0 || index == 1);
1006 27708 : Int32BinopMatcher m(node);
1007 27708 : if (m.IsFoldable()) {
1008 : int32_t val;
1009 : bool ovf = base::bits::SignedMulOverflow32(m.left().Value(),
1010 20334 : m.right().Value(), &val);
1011 20334 : return ReplaceInt32(index == 0 ? val : ovf);
1012 : }
1013 7374 : if (m.right().Is(0)) {
1014 : return Replace(m.right().node());
1015 : }
1016 7298 : if (m.right().Is(1)) {
1017 1692 : return index == 0 ? Replace(m.left().node()) : ReplaceInt32(0);
1018 : }
1019 5606 : break;
1020 : }
1021 : default:
1022 : break;
1023 : }
1024 : return NoChange();
1025 : }
1026 :
1027 :
1028 90018 : Reduction MachineOperatorReducer::ReduceWord32Shifts(Node* node) {
1029 : DCHECK((node->opcode() == IrOpcode::kWord32Shl) ||
1030 : (node->opcode() == IrOpcode::kWord32Shr) ||
1031 : (node->opcode() == IrOpcode::kWord32Sar));
1032 90018 : if (machine()->Word32ShiftIsSafe()) {
1033 : // Remove the explicit 'and' with 0x1f if the shift provided by the machine
1034 : // instruction matches that required by JavaScript.
1035 89577 : Int32BinopMatcher m(node);
1036 89577 : if (m.right().IsWord32And()) {
1037 2806 : Int32BinopMatcher mright(m.right().node());
1038 2806 : if (mright.right().Is(0x1f)) {
1039 1329 : node->ReplaceInput(1, mright.left().node());
1040 1329 : return Changed(node);
1041 : }
1042 : }
1043 : }
1044 : return NoChange();
1045 : }
1046 :
1047 :
1048 56214 : Reduction MachineOperatorReducer::ReduceWord32Shl(Node* node) {
1049 : DCHECK_EQ(IrOpcode::kWord32Shl, node->opcode());
1050 56214 : Int32BinopMatcher m(node);
1051 56214 : if (m.right().Is(0)) return Replace(m.left().node()); // x << 0 => x
1052 55357 : if (m.IsFoldable()) { // K << K => K
1053 15249 : return ReplaceInt32(m.left().Value() << m.right().Value());
1054 : }
1055 40108 : if (m.right().IsInRange(1, 31)) {
1056 : // (x >>> K) << K => x & ~(2^K - 1)
1057 : // (x >> K) << K => x & ~(2^K - 1)
1058 35790 : if (m.left().IsWord32Sar() || m.left().IsWord32Shr()) {
1059 12768 : Int32BinopMatcher mleft(m.left().node());
1060 12768 : if (mleft.right().Is(m.right().Value())) {
1061 11738 : node->ReplaceInput(0, mleft.left().node());
1062 : node->ReplaceInput(1,
1063 23476 : Uint32Constant(~((1U << m.right().Value()) - 1U)));
1064 11738 : NodeProperties::ChangeOp(node, machine()->Word32And());
1065 11738 : Reduction reduction = ReduceWord32And(node);
1066 11738 : return reduction.Changed() ? reduction : Changed(node);
1067 : }
1068 : }
1069 : }
1070 28370 : return ReduceWord32Shifts(node);
1071 : }
1072 :
1073 337054 : Reduction MachineOperatorReducer::ReduceWord64Shl(Node* node) {
1074 : DCHECK_EQ(IrOpcode::kWord64Shl, node->opcode());
1075 337054 : Int64BinopMatcher m(node);
1076 337055 : if (m.right().Is(0)) return Replace(m.left().node()); // x << 0 => x
1077 336502 : if (m.IsFoldable()) { // K << K => K
1078 204955 : return ReplaceInt64(m.left().Value() << m.right().Value());
1079 : }
1080 : return NoChange();
1081 : }
1082 :
1083 45260 : Reduction MachineOperatorReducer::ReduceWord32Shr(Node* node) {
1084 45260 : Uint32BinopMatcher m(node);
1085 45261 : if (m.right().Is(0)) return Replace(m.left().node()); // x >>> 0 => x
1086 40114 : if (m.IsFoldable()) { // K >>> K => K
1087 12765 : return ReplaceInt32(m.left().Value() >> m.right().Value());
1088 : }
1089 27349 : if (m.left().IsWord32And() && m.right().HasValue()) {
1090 63 : Uint32BinopMatcher mleft(m.left().node());
1091 63 : if (mleft.right().HasValue()) {
1092 60 : uint32_t shift = m.right().Value() & 0x1f;
1093 60 : uint32_t mask = mleft.right().Value();
1094 60 : if ((mask >> shift) == 0) {
1095 : // (m >>> s) == 0 implies ((x & m) >>> s) == 0
1096 31 : return ReplaceInt32(0);
1097 : }
1098 : }
1099 : }
1100 27318 : return ReduceWord32Shifts(node);
1101 : }
1102 :
1103 34789 : Reduction MachineOperatorReducer::ReduceWord64Shr(Node* node) {
1104 : DCHECK_EQ(IrOpcode::kWord64Shr, node->opcode());
1105 34789 : Uint64BinopMatcher m(node);
1106 34789 : if (m.right().Is(0)) return Replace(m.left().node()); // x >>> 0 => x
1107 34236 : if (m.IsFoldable()) { // K >> K => K
1108 33964 : return ReplaceInt64(m.left().Value() >> m.right().Value());
1109 : }
1110 : return NoChange();
1111 : }
1112 :
1113 48378 : Reduction MachineOperatorReducer::ReduceWord32Sar(Node* node) {
1114 48378 : Int32BinopMatcher m(node);
1115 48378 : if (m.right().Is(0)) return Replace(m.left().node()); // x >> 0 => x
1116 47427 : if (m.IsFoldable()) { // K >> K => K
1117 13035 : return ReplaceInt32(m.left().Value() >> m.right().Value());
1118 : }
1119 34392 : if (m.left().IsWord32Shl()) {
1120 1578 : Int32BinopMatcher mleft(m.left().node());
1121 1578 : if (mleft.left().IsComparison()) {
1122 116 : if (m.right().Is(31) && mleft.right().Is(31)) {
1123 : // Comparison << 31 >> 31 => 0 - Comparison
1124 58 : node->ReplaceInput(0, Int32Constant(0));
1125 58 : node->ReplaceInput(1, mleft.left().node());
1126 58 : NodeProperties::ChangeOp(node, machine()->Int32Sub());
1127 58 : Reduction const reduction = ReduceInt32Sub(node);
1128 58 : return reduction.Changed() ? reduction : Changed(node);
1129 : }
1130 1520 : } else if (mleft.left().IsLoad()) {
1131 : LoadRepresentation const rep =
1132 4 : LoadRepresentationOf(mleft.left().node()->op());
1133 10 : if (m.right().Is(24) && mleft.right().Is(24) &&
1134 : rep == MachineType::Int8()) {
1135 : // Load[kMachInt8] << 24 >> 24 => Load[kMachInt8]
1136 : return Replace(mleft.left().node());
1137 : }
1138 3 : if (m.right().Is(16) && mleft.right().Is(16) &&
1139 : rep == MachineType::Int16()) {
1140 : // Load[kMachInt16] << 16 >> 16 => Load[kMachInt8]
1141 : return Replace(mleft.left().node());
1142 : }
1143 : }
1144 : }
1145 34330 : return ReduceWord32Shifts(node);
1146 : }
1147 :
1148 215313 : Reduction MachineOperatorReducer::ReduceWord64Sar(Node* node) {
1149 215313 : Int64BinopMatcher m(node);
1150 215313 : if (m.right().Is(0)) return Replace(m.left().node()); // x >> 0 => x
1151 214760 : if (m.IsFoldable()) {
1152 33972 : return ReplaceInt64(m.left().Value() >> m.right().Value());
1153 : }
1154 : return NoChange();
1155 : }
1156 :
1157 547823 : Reduction MachineOperatorReducer::ReduceWord32And(Node* node) {
1158 : DCHECK_EQ(IrOpcode::kWord32And, node->opcode());
1159 547823 : Int32BinopMatcher m(node);
1160 547823 : if (m.right().Is(0)) return Replace(m.right().node()); // x & 0 => 0
1161 545636 : if (m.right().Is(-1)) return Replace(m.left().node()); // x & -1 => x
1162 546240 : if (m.left().IsComparison() && m.right().Is(1)) { // CMP & 1 => CMP
1163 : return Replace(m.left().node());
1164 : }
1165 544844 : if (m.IsFoldable()) { // K & K => K
1166 27799 : return ReplaceInt32(m.left().Value() & m.right().Value());
1167 : }
1168 517045 : if (m.LeftEqualsRight()) return Replace(m.left().node()); // x & x => x
1169 517021 : if (m.left().IsWord32And() && m.right().HasValue()) {
1170 19763 : Int32BinopMatcher mleft(m.left().node());
1171 19763 : if (mleft.right().HasValue()) { // (x & K) & K => x & K
1172 19747 : node->ReplaceInput(0, mleft.left().node());
1173 : node->ReplaceInput(
1174 39494 : 1, Int32Constant(m.right().Value() & mleft.right().Value()));
1175 19747 : Reduction const reduction = ReduceWord32And(node);
1176 19747 : return reduction.Changed() ? reduction : Changed(node);
1177 : }
1178 : }
1179 497274 : if (m.right().IsNegativePowerOf2()) {
1180 325503 : int32_t const mask = m.right().Value();
1181 325503 : if (m.left().IsWord32Shl()) {
1182 2668 : Uint32BinopMatcher mleft(m.left().node());
1183 5336 : if (mleft.right().HasValue() &&
1184 2668 : (mleft.right().Value() & 0x1f) >=
1185 2668 : base::bits::CountTrailingZeros32(mask)) {
1186 : // (x << L) & (-1 << K) => x << L iff L >= K
1187 2638 : return Replace(mleft.node());
1188 : }
1189 322835 : } else if (m.left().IsInt32Add()) {
1190 123120 : Int32BinopMatcher mleft(m.left().node());
1191 219130 : if (mleft.right().HasValue() &&
1192 96010 : (mleft.right().Value() & mask) == mleft.right().Value()) {
1193 : // (x + (K << L)) & (-1 << L) => (x & (-1 << L)) + (K << L)
1194 95841 : node->ReplaceInput(0, Word32And(mleft.left().node(), m.right().node()));
1195 95841 : node->ReplaceInput(1, mleft.right().node());
1196 95841 : NodeProperties::ChangeOp(node, machine()->Int32Add());
1197 95841 : Reduction const reduction = ReduceInt32Add(node);
1198 95841 : return reduction.Changed() ? reduction : Changed(node);
1199 : }
1200 27279 : if (mleft.left().IsInt32Mul()) {
1201 2923 : Int32BinopMatcher mleftleft(mleft.left().node());
1202 5846 : if (mleftleft.right().IsMultipleOf(-mask)) {
1203 : // (y * (K << L) + x) & (-1 << L) => (x & (-1 << L)) + y * (K << L)
1204 : node->ReplaceInput(0,
1205 2923 : Word32And(mleft.right().node(), m.right().node()));
1206 2923 : node->ReplaceInput(1, mleftleft.node());
1207 2923 : NodeProperties::ChangeOp(node, machine()->Int32Add());
1208 2923 : Reduction const reduction = ReduceInt32Add(node);
1209 2923 : return reduction.Changed() ? reduction : Changed(node);
1210 : }
1211 : }
1212 24356 : if (mleft.right().IsInt32Mul()) {
1213 9724 : Int32BinopMatcher mleftright(mleft.right().node());
1214 19448 : if (mleftright.right().IsMultipleOf(-mask)) {
1215 : // (x + y * (K << L)) & (-1 << L) => (x & (-1 << L)) + y * (K << L)
1216 : node->ReplaceInput(0,
1217 9706 : Word32And(mleft.left().node(), m.right().node()));
1218 9706 : node->ReplaceInput(1, mleftright.node());
1219 9706 : NodeProperties::ChangeOp(node, machine()->Int32Add());
1220 9706 : Reduction const reduction = ReduceInt32Add(node);
1221 9706 : return reduction.Changed() ? reduction : Changed(node);
1222 : }
1223 : }
1224 14650 : if (mleft.left().IsWord32Shl()) {
1225 38 : Int32BinopMatcher mleftleft(mleft.left().node());
1226 114 : if (mleftleft.right().Is(base::bits::CountTrailingZeros32(mask))) {
1227 : // (y << L + x) & (-1 << L) => (x & (-1 << L)) + y << L
1228 : node->ReplaceInput(0,
1229 31 : Word32And(mleft.right().node(), m.right().node()));
1230 31 : node->ReplaceInput(1, mleftleft.node());
1231 31 : NodeProperties::ChangeOp(node, machine()->Int32Add());
1232 31 : Reduction const reduction = ReduceInt32Add(node);
1233 31 : return reduction.Changed() ? reduction : Changed(node);
1234 : }
1235 : }
1236 14619 : if (mleft.right().IsWord32Shl()) {
1237 9161 : Int32BinopMatcher mleftright(mleft.right().node());
1238 27483 : if (mleftright.right().Is(base::bits::CountTrailingZeros32(mask))) {
1239 : // (x + y << L) & (-1 << L) => (x & (-1 << L)) + y << L
1240 : node->ReplaceInput(0,
1241 3276 : Word32And(mleft.left().node(), m.right().node()));
1242 3276 : node->ReplaceInput(1, mleftright.node());
1243 3276 : NodeProperties::ChangeOp(node, machine()->Int32Add());
1244 3276 : Reduction const reduction = ReduceInt32Add(node);
1245 3276 : return reduction.Changed() ? reduction : Changed(node);
1246 : }
1247 : }
1248 199715 : } else if (m.left().IsInt32Mul()) {
1249 5949 : Int32BinopMatcher mleft(m.left().node());
1250 11898 : if (mleft.right().IsMultipleOf(-mask)) {
1251 : // (x * (K << L)) & (-1 << L) => x * (K << L)
1252 5893 : return Replace(mleft.node());
1253 : }
1254 : }
1255 : }
1256 : return NoChange();
1257 : }
1258 :
1259 23982 : Reduction MachineOperatorReducer::TryMatchWord32Ror(Node* node) {
1260 : DCHECK(IrOpcode::kWord32Or == node->opcode() ||
1261 : IrOpcode::kWord32Xor == node->opcode());
1262 23982 : Int32BinopMatcher m(node);
1263 : Node* shl = nullptr;
1264 : Node* shr = nullptr;
1265 : // Recognize rotation, we are matching:
1266 : // * x << y | x >>> (32 - y) => x ror (32 - y), i.e x rol y
1267 : // * x << (32 - y) | x >>> y => x ror y
1268 : // * x << y ^ x >>> (32 - y) => x ror (32 - y), i.e. x rol y
1269 : // * x << (32 - y) ^ x >>> y => x ror y
1270 : // as well as their commuted form.
1271 28171 : if (m.left().IsWord32Shl() && m.right().IsWord32Shr()) {
1272 : shl = m.left().node();
1273 : shr = m.right().node();
1274 23695 : } else if (m.left().IsWord32Shr() && m.right().IsWord32Shl()) {
1275 : shl = m.right().node();
1276 : shr = m.left().node();
1277 : } else {
1278 : return NoChange();
1279 : }
1280 :
1281 713 : Int32BinopMatcher mshl(shl);
1282 713 : Int32BinopMatcher mshr(shr);
1283 713 : if (mshl.left().node() != mshr.left().node()) return NoChange();
1284 :
1285 533 : if (mshl.right().HasValue() && mshr.right().HasValue()) {
1286 : // Case where y is a constant.
1287 367 : if (mshl.right().Value() + mshr.right().Value() != 32) return NoChange();
1288 : } else {
1289 : Node* sub = nullptr;
1290 : Node* y = nullptr;
1291 166 : if (mshl.right().IsInt32Sub()) {
1292 : sub = mshl.right().node();
1293 : y = mshr.right().node();
1294 159 : } else if (mshr.right().IsInt32Sub()) {
1295 : sub = mshr.right().node();
1296 : y = mshl.right().node();
1297 : } else {
1298 152 : return NoChange();
1299 : }
1300 :
1301 14 : Int32BinopMatcher msub(sub);
1302 28 : if (!msub.left().Is(32) || msub.right().node() != y) return NoChange();
1303 : }
1304 :
1305 381 : node->ReplaceInput(0, mshl.left().node());
1306 381 : node->ReplaceInput(1, mshr.right().node());
1307 381 : NodeProperties::ChangeOp(node, machine()->Word32Ror());
1308 : return Changed(node);
1309 : }
1310 :
1311 79844 : Reduction MachineOperatorReducer::ReduceWord32Or(Node* node) {
1312 : DCHECK_EQ(IrOpcode::kWord32Or, node->opcode());
1313 79844 : Int32BinopMatcher m(node);
1314 79845 : if (m.right().Is(0)) return Replace(m.left().node()); // x | 0 => x
1315 38248 : if (m.right().Is(-1)) return Replace(m.right().node()); // x | -1 => -1
1316 34631 : if (m.IsFoldable()) { // K | K => K
1317 20802 : return ReplaceInt32(m.left().Value() | m.right().Value());
1318 : }
1319 13829 : if (m.LeftEqualsRight()) return Replace(m.left().node()); // x | x => x
1320 :
1321 13780 : return TryMatchWord32Ror(node);
1322 : }
1323 :
1324 32122 : Reduction MachineOperatorReducer::ReduceWord32Xor(Node* node) {
1325 : DCHECK_EQ(IrOpcode::kWord32Xor, node->opcode());
1326 32122 : Int32BinopMatcher m(node);
1327 32122 : if (m.right().Is(0)) return Replace(m.left().node()); // x ^ 0 => x
1328 31417 : if (m.IsFoldable()) { // K ^ K => K
1329 21180 : return ReplaceInt32(m.left().Value() ^ m.right().Value());
1330 : }
1331 10237 : if (m.LeftEqualsRight()) return ReplaceInt32(0); // x ^ x => 0
1332 10522 : if (m.left().IsWord32Xor() && m.right().Is(-1)) {
1333 90 : Int32BinopMatcher mleft(m.left().node());
1334 90 : if (mleft.right().Is(-1)) { // (x ^ -1) ^ -1 => x
1335 16 : return Replace(mleft.left().node());
1336 : }
1337 : }
1338 :
1339 10202 : return TryMatchWord32Ror(node);
1340 : }
1341 :
1342 4800 : Reduction MachineOperatorReducer::ReduceFloat64InsertLowWord32(Node* node) {
1343 : DCHECK_EQ(IrOpcode::kFloat64InsertLowWord32, node->opcode());
1344 : Float64Matcher mlhs(node->InputAt(0));
1345 : Uint32Matcher mrhs(node->InputAt(1));
1346 4800 : if (mlhs.HasValue() && mrhs.HasValue()) {
1347 : return ReplaceFloat64(bit_cast<double>(
1348 4800 : (bit_cast<uint64_t>(mlhs.Value()) & V8_UINT64_C(0xFFFFFFFF00000000)) |
1349 : mrhs.Value()));
1350 : }
1351 : return NoChange();
1352 : }
1353 :
1354 :
1355 4800 : Reduction MachineOperatorReducer::ReduceFloat64InsertHighWord32(Node* node) {
1356 : DCHECK_EQ(IrOpcode::kFloat64InsertHighWord32, node->opcode());
1357 : Float64Matcher mlhs(node->InputAt(0));
1358 : Uint32Matcher mrhs(node->InputAt(1));
1359 4800 : if (mlhs.HasValue() && mrhs.HasValue()) {
1360 : return ReplaceFloat64(bit_cast<double>(
1361 9600 : (bit_cast<uint64_t>(mlhs.Value()) & V8_UINT64_C(0xFFFFFFFF)) |
1362 4800 : (static_cast<uint64_t>(mrhs.Value()) << 32)));
1363 : }
1364 : return NoChange();
1365 : }
1366 :
1367 :
1368 : namespace {
1369 :
1370 : bool IsFloat64RepresentableAsFloat32(const Float64Matcher& m) {
1371 191204 : if (m.HasValue()) {
1372 89814 : double v = m.Value();
1373 89814 : float fv = static_cast<float>(v);
1374 89814 : return static_cast<double>(fv) == v;
1375 : }
1376 : return false;
1377 : }
1378 :
1379 : } // namespace
1380 :
1381 :
1382 193058 : Reduction MachineOperatorReducer::ReduceFloat64Compare(Node* node) {
1383 : DCHECK((IrOpcode::kFloat64Equal == node->opcode()) ||
1384 : (IrOpcode::kFloat64LessThan == node->opcode()) ||
1385 : (IrOpcode::kFloat64LessThanOrEqual == node->opcode()));
1386 : // As all Float32 values have an exact representation in Float64, comparing
1387 : // two Float64 values both converted from Float32 is equivalent to comparing
1388 : // the original Float32s, so we can ignore the conversions. We can also reduce
1389 : // comparisons of converted Float64 values against constants that can be
1390 : // represented exactly as Float32.
1391 191628 : Float64BinopMatcher m(node);
1392 193099 : if ((m.left().IsChangeFloat32ToFloat64() &&
1393 190889 : m.right().IsChangeFloat32ToFloat64()) ||
1394 732 : (m.left().IsChangeFloat32ToFloat64() &&
1395 382100 : IsFloat64RepresentableAsFloat32(m.right())) ||
1396 87796 : (IsFloat64RepresentableAsFloat32(m.left()) &&
1397 : m.right().IsChangeFloat32ToFloat64())) {
1398 1430 : switch (node->opcode()) {
1399 : case IrOpcode::kFloat64Equal:
1400 308 : NodeProperties::ChangeOp(node, machine()->Float32Equal());
1401 308 : break;
1402 : case IrOpcode::kFloat64LessThan:
1403 815 : NodeProperties::ChangeOp(node, machine()->Float32LessThan());
1404 815 : break;
1405 : case IrOpcode::kFloat64LessThanOrEqual:
1406 307 : NodeProperties::ChangeOp(node, machine()->Float32LessThanOrEqual());
1407 307 : break;
1408 : default:
1409 : return NoChange();
1410 : }
1411 : node->ReplaceInput(
1412 1430 : 0, m.left().HasValue()
1413 274 : ? Float32Constant(static_cast<float>(m.left().Value()))
1414 3134 : : m.left().InputAt(0));
1415 : node->ReplaceInput(
1416 1430 : 1, m.right().HasValue()
1417 417 : ? Float32Constant(static_cast<float>(m.right().Value()))
1418 3277 : : m.right().InputAt(0));
1419 : return Changed(node);
1420 : }
1421 : return NoChange();
1422 : }
1423 :
1424 18064 : Reduction MachineOperatorReducer::ReduceFloat64RoundDown(Node* node) {
1425 : DCHECK_EQ(IrOpcode::kFloat64RoundDown, node->opcode());
1426 : Float64Matcher m(node->InputAt(0));
1427 18064 : if (m.HasValue()) {
1428 : return ReplaceFloat64(Floor(m.Value()));
1429 : }
1430 : return NoChange();
1431 : }
1432 :
1433 1016262 : CommonOperatorBuilder* MachineOperatorReducer::common() const {
1434 1016262 : return jsgraph()->common();
1435 : }
1436 :
1437 :
1438 549672 : MachineOperatorBuilder* MachineOperatorReducer::machine() const {
1439 549672 : return jsgraph()->machine();
1440 : }
1441 :
1442 :
1443 1168049 : Graph* MachineOperatorReducer::graph() const { return jsgraph()->graph(); }
1444 :
1445 : } // namespace compiler
1446 : } // namespace internal
1447 : } // namespace v8
|