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/compiler/diamond.h"
11 : #include "src/compiler/graph.h"
12 : #include "src/compiler/js-graph.h"
13 : #include "src/compiler/node-matchers.h"
14 : #include "src/conversions-inl.h"
15 :
16 : namespace v8 {
17 : namespace internal {
18 : namespace compiler {
19 :
20 1650655 : MachineOperatorReducer::MachineOperatorReducer(JSGraph* jsgraph,
21 : bool allow_signalling_nan)
22 1650655 : : jsgraph_(jsgraph), allow_signalling_nan_(allow_signalling_nan) {}
23 :
24 3301288 : MachineOperatorReducer::~MachineOperatorReducer() {}
25 :
26 :
27 80229 : Node* MachineOperatorReducer::Float32Constant(volatile float value) {
28 240687 : return graph()->NewNode(common()->Float32Constant(value));
29 : }
30 :
31 :
32 113802 : Node* MachineOperatorReducer::Float64Constant(volatile double value) {
33 227604 : return jsgraph()->Float64Constant(value);
34 : }
35 :
36 :
37 571776 : Node* MachineOperatorReducer::Int32Constant(int32_t value) {
38 571776 : return jsgraph()->Int32Constant(value);
39 : }
40 :
41 :
42 550477 : Node* MachineOperatorReducer::Int64Constant(int64_t value) {
43 1100955 : return graph()->NewNode(common()->Int64Constant(value));
44 : }
45 :
46 0 : Node* MachineOperatorReducer::Float64Mul(Node* lhs, Node* rhs) {
47 0 : return graph()->NewNode(machine()->Float64Mul(), lhs, rhs);
48 : }
49 :
50 0 : Node* MachineOperatorReducer::Float64PowHalf(Node* value) {
51 : value =
52 0 : graph()->NewNode(machine()->Float64Add(), Float64Constant(0.0), value);
53 : Diamond d(graph(), common(),
54 : graph()->NewNode(machine()->Float64LessThanOrEqual(), value,
55 : Float64Constant(-V8_INFINITY)),
56 0 : BranchHint::kFalse);
57 : return d.Phi(MachineRepresentation::kFloat64, Float64Constant(V8_INFINITY),
58 0 : graph()->NewNode(machine()->Float64Sqrt(), value));
59 : }
60 :
61 115010 : Node* MachineOperatorReducer::Word32And(Node* lhs, Node* rhs) {
62 115010 : Node* const node = graph()->NewNode(machine()->Word32And(), lhs, rhs);
63 115010 : Reduction const reduction = ReduceWord32And(node);
64 115010 : return reduction.Changed() ? reduction.replacement() : node;
65 : }
66 :
67 :
68 6829 : Node* MachineOperatorReducer::Word32Sar(Node* lhs, uint32_t rhs) {
69 6829 : if (rhs == 0) return lhs;
70 13278 : return graph()->NewNode(machine()->Word32Sar(), lhs, Uint32Constant(rhs));
71 : }
72 :
73 :
74 6804 : Node* MachineOperatorReducer::Word32Shr(Node* lhs, uint32_t rhs) {
75 6804 : if (rhs == 0) return lhs;
76 13184 : return graph()->NewNode(machine()->Word32Shr(), lhs, Uint32Constant(rhs));
77 : }
78 :
79 :
80 12 : Node* MachineOperatorReducer::Word32Equal(Node* lhs, Node* rhs) {
81 24 : return graph()->NewNode(machine()->Word32Equal(), lhs, rhs);
82 : }
83 :
84 :
85 7618 : Node* MachineOperatorReducer::Int32Add(Node* lhs, Node* rhs) {
86 7618 : Node* const node = graph()->NewNode(machine()->Int32Add(), lhs, rhs);
87 7618 : Reduction const reduction = ReduceInt32Add(node);
88 7618 : return reduction.Changed() ? reduction.replacement() : node;
89 : }
90 :
91 :
92 2262 : Node* MachineOperatorReducer::Int32Sub(Node* lhs, Node* rhs) {
93 2262 : Node* const node = graph()->NewNode(machine()->Int32Sub(), lhs, rhs);
94 2262 : Reduction const reduction = ReduceInt32Sub(node);
95 2262 : return reduction.Changed() ? reduction.replacement() : node;
96 : }
97 :
98 :
99 3352 : Node* MachineOperatorReducer::Int32Mul(Node* lhs, Node* rhs) {
100 6704 : return graph()->NewNode(machine()->Int32Mul(), lhs, rhs);
101 : }
102 :
103 :
104 5248 : Node* MachineOperatorReducer::Int32Div(Node* dividend, int32_t divisor) {
105 : DCHECK_NE(0, divisor);
106 : DCHECK_NE(std::numeric_limits<int32_t>::min(), divisor);
107 : base::MagicNumbersForDivision<uint32_t> const mag =
108 5248 : base::SignedDivisionByConstant(bit_cast<uint32_t>(divisor));
109 : Node* quotient = graph()->NewNode(machine()->Int32MulHigh(), dividend,
110 5248 : Uint32Constant(mag.multiplier));
111 10496 : if (divisor > 0 && bit_cast<int32_t>(mag.multiplier) < 0) {
112 1454 : quotient = Int32Add(quotient, dividend);
113 3794 : } else if (divisor < 0 && bit_cast<int32_t>(mag.multiplier) > 0) {
114 0 : quotient = Int32Sub(quotient, dividend);
115 : }
116 5248 : return Int32Add(Word32Sar(quotient, mag.shift), Word32Shr(dividend, 31));
117 : }
118 :
119 :
120 320 : Node* MachineOperatorReducer::Uint32Div(Node* dividend, uint32_t divisor) {
121 : DCHECK_LT(0u, divisor);
122 : // If the divisor is even, we can avoid using the expensive fixup by shifting
123 : // the dividend upfront.
124 : unsigned const shift = base::bits::CountTrailingZeros32(divisor);
125 320 : dividend = Word32Shr(dividend, shift);
126 320 : divisor >>= shift;
127 : // Compute the magic number for the (shifted) divisor.
128 : base::MagicNumbersForDivision<uint32_t> const mag =
129 320 : base::UnsignedDivisionByConstant(divisor, shift);
130 : Node* quotient = graph()->NewNode(machine()->Uint32MulHigh(), dividend,
131 640 : Uint32Constant(mag.multiplier));
132 320 : if (mag.add) {
133 : DCHECK_LE(1u, mag.shift);
134 : quotient = Word32Shr(
135 : Int32Add(Word32Shr(Int32Sub(dividend, quotient), 1), quotient),
136 34 : mag.shift - 1);
137 : } else {
138 286 : quotient = Word32Shr(quotient, mag.shift);
139 : }
140 320 : return quotient;
141 : }
142 :
143 :
144 : // Perform constant folding and strength reduction on machine operators.
145 90748364 : Reduction MachineOperatorReducer::Reduce(Node* node) {
146 90748364 : switch (node->opcode()) {
147 : case IrOpcode::kProjection:
148 256815 : return ReduceProjection(ProjectionIndexOf(node->op()), node->InputAt(0));
149 : case IrOpcode::kWord32And:
150 382915 : return ReduceWord32And(node);
151 : case IrOpcode::kWord32Or:
152 55869 : return ReduceWord32Or(node);
153 : case IrOpcode::kWord32Xor:
154 25034 : return ReduceWord32Xor(node);
155 : case IrOpcode::kWord32Shl:
156 39597 : return ReduceWord32Shl(node);
157 : case IrOpcode::kWord64Shl:
158 217353 : return ReduceWord64Shl(node);
159 : case IrOpcode::kWord32Shr:
160 47454 : return ReduceWord32Shr(node);
161 : case IrOpcode::kWord64Shr:
162 31116 : return ReduceWord64Shr(node);
163 : case IrOpcode::kWord32Sar:
164 35950 : return ReduceWord32Sar(node);
165 : case IrOpcode::kWord64Sar:
166 197762 : return ReduceWord64Sar(node);
167 : case IrOpcode::kWord32Ror: {
168 1879 : Int32BinopMatcher m(node);
169 3416 : if (m.right().Is(0)) return Replace(m.left().node()); // x ror 0 => x
170 1830 : if (m.IsFoldable()) { // K ror K => K
171 : return ReplaceInt32(
172 2976 : base::bits::RotateRight32(m.left().Value(), m.right().Value()));
173 : }
174 342 : break;
175 : }
176 : case IrOpcode::kWord32Equal: {
177 383976 : Int32BinopMatcher m(node);
178 383976 : if (m.IsFoldable()) { // K == K => K
179 79315 : return ReplaceBool(m.left().Value() == m.right().Value());
180 : }
181 345787 : if (m.left().IsInt32Sub() && m.right().Is(0)) { // x - y == 0 => x == y
182 871 : Int32BinopMatcher msub(m.left().node());
183 871 : node->ReplaceInput(0, msub.left().node());
184 871 : node->ReplaceInput(1, msub.right().node());
185 : return Changed(node);
186 : }
187 : // TODO(turbofan): fold HeapConstant, ExternalReference, pointer compares
188 343992 : if (m.LeftEqualsRight()) return ReplaceBool(true); // x == x => true
189 343774 : break;
190 : }
191 : case IrOpcode::kWord64Equal: {
192 1203322 : Int64BinopMatcher m(node);
193 1203319 : if (m.IsFoldable()) { // K == K => K
194 7171 : return ReplaceBool(m.left().Value() == m.right().Value());
195 : }
196 1203319 : if (m.left().IsInt64Sub() && m.right().Is(0)) { // x - y == 0 => x == y
197 0 : Int64BinopMatcher msub(m.left().node());
198 0 : node->ReplaceInput(0, msub.left().node());
199 0 : node->ReplaceInput(1, msub.right().node());
200 : return Changed(node);
201 : }
202 : // TODO(turbofan): fold HeapConstant, ExternalReference, pointer compares
203 1203319 : if (m.LeftEqualsRight()) return ReplaceBool(true); // x == x => true
204 1196148 : break;
205 : }
206 : case IrOpcode::kInt32Add:
207 377921 : return ReduceInt32Add(node);
208 : case IrOpcode::kInt64Add:
209 620539 : return ReduceInt64Add(node);
210 : case IrOpcode::kInt32Sub:
211 64326 : return ReduceInt32Sub(node);
212 : case IrOpcode::kInt64Sub:
213 161573 : return ReduceInt64Sub(node);
214 : case IrOpcode::kInt32Mul: {
215 31882 : Int32BinopMatcher m(node);
216 53206 : if (m.right().Is(0)) return Replace(m.right().node()); // x * 0 => 0
217 31442 : if (m.right().Is(1)) return Replace(m.left().node()); // x * 1 => x
218 31059 : if (m.IsFoldable()) { // K * K => K
219 19685 : return ReplaceInt32(m.left().Value() * m.right().Value());
220 : }
221 11374 : if (m.right().Is(-1)) { // x * -1 => 0 - x
222 92 : node->ReplaceInput(0, Int32Constant(0));
223 92 : node->ReplaceInput(1, m.left().node());
224 92 : NodeProperties::ChangeOp(node, machine()->Int32Sub());
225 : return Changed(node);
226 : }
227 11282 : if (m.right().IsPowerOf2()) { // x * 2^n => x << n
228 1448 : node->ReplaceInput(1, Int32Constant(WhichPowerOf2(m.right().Value())));
229 724 : NodeProperties::ChangeOp(node, machine()->Word32Shl());
230 724 : Reduction reduction = ReduceWord32Shl(node);
231 724 : return reduction.Changed() ? reduction : Changed(node);
232 : }
233 10558 : break;
234 : }
235 : case IrOpcode::kInt32MulWithOverflow: {
236 6544 : Int32BinopMatcher m(node);
237 6544 : if (m.right().Is(2)) {
238 212 : node->ReplaceInput(1, m.left().node());
239 212 : NodeProperties::ChangeOp(node, machine()->Int32AddWithOverflow());
240 3290 : return Changed(node);
241 : }
242 6332 : if (m.right().Is(-1)) {
243 3078 : node->ReplaceInput(0, Int32Constant(0));
244 3078 : node->ReplaceInput(1, m.left().node());
245 3078 : NodeProperties::ChangeOp(node, machine()->Int32SubWithOverflow());
246 : return Changed(node);
247 : }
248 3254 : break;
249 : }
250 : case IrOpcode::kInt32Div:
251 23532 : return ReduceInt32Div(node);
252 : case IrOpcode::kUint32Div:
253 22741 : return ReduceUint32Div(node);
254 : case IrOpcode::kInt32Mod:
255 34882 : return ReduceInt32Mod(node);
256 : case IrOpcode::kUint32Mod:
257 22928 : return ReduceUint32Mod(node);
258 : case IrOpcode::kInt32LessThan: {
259 221386 : Int32BinopMatcher m(node);
260 221395 : if (m.IsFoldable()) { // K < K => K
261 47913 : return ReplaceBool(m.left().Value() < m.right().Value());
262 : }
263 197483 : if (m.LeftEqualsRight()) return ReplaceBool(false); // x < x => false
264 198738 : if (m.left().IsWord32Or() && m.right().Is(0)) {
265 : // (x | K) < 0 => true or (K | x) < 0 => true iff K < 0
266 1219 : Int32BinopMatcher mleftmatcher(m.left().node());
267 2438 : if (mleftmatcher.left().IsNegative() ||
268 : mleftmatcher.right().IsNegative()) {
269 75 : return ReplaceBool(true);
270 : }
271 : }
272 197394 : break;
273 : }
274 : case IrOpcode::kInt32LessThanOrEqual: {
275 26598 : Int32BinopMatcher m(node);
276 26598 : if (m.IsFoldable()) { // K <= K => K
277 42226 : return ReplaceBool(m.left().Value() <= m.right().Value());
278 : }
279 5488 : if (m.LeftEqualsRight()) return ReplaceBool(true); // x <= x => true
280 5482 : break;
281 : }
282 : case IrOpcode::kUint32LessThan: {
283 117433 : Uint32BinopMatcher m(node);
284 146623 : if (m.left().Is(kMaxUInt32)) return ReplaceBool(false); // M < x => false
285 117067 : if (m.right().Is(0)) return ReplaceBool(false); // x < 0 => false
286 116347 : if (m.IsFoldable()) { // K < K => K
287 27244 : return ReplaceBool(m.left().Value() < m.right().Value());
288 : }
289 89103 : if (m.LeftEqualsRight()) return ReplaceBool(false); // x < x => false
290 88529 : if (m.left().IsWord32Sar() && m.right().HasValue()) {
291 286 : Int32BinopMatcher mleft(m.left().node());
292 286 : if (mleft.right().HasValue()) {
293 : // (x >> K) < C => x < (C << K)
294 : // when C < (M >> K)
295 286 : const uint32_t c = m.right().Value();
296 286 : const uint32_t k = mleft.right().Value() & 0x1f;
297 286 : if (c < static_cast<uint32_t>(kMaxInt >> k)) {
298 286 : node->ReplaceInput(0, mleft.left().node());
299 572 : node->ReplaceInput(1, Uint32Constant(c << k));
300 286 : return Changed(node);
301 : }
302 : // TODO(turbofan): else the comparison is always true.
303 : }
304 : }
305 88243 : break;
306 : }
307 : case IrOpcode::kUint32LessThanOrEqual: {
308 50708 : Uint32BinopMatcher m(node);
309 71362 : if (m.left().Is(0)) return ReplaceBool(true); // 0 <= x => true
310 50096 : if (m.right().Is(kMaxUInt32)) return ReplaceBool(true); // x <= M => true
311 49748 : if (m.IsFoldable()) { // K <= K => K
312 19687 : return ReplaceBool(m.left().Value() <= m.right().Value());
313 : }
314 30061 : if (m.LeftEqualsRight()) return ReplaceBool(true); // x <= x => true
315 30054 : break;
316 : }
317 : case IrOpcode::kFloat32Sub: {
318 79370 : Float32BinopMatcher m(node);
319 160120 : if (allow_signalling_nan_ && m.right().Is(0) &&
320 1380 : (copysign(1.0, m.right().Value()) > 0)) {
321 79363 : return Replace(m.left().node()); // x - 0 => x
322 : }
323 78680 : if (m.right().IsNaN()) { // x - NaN => NaN
324 : // Do some calculation to make a signalling NaN quiet.
325 1386 : return ReplaceFloat32(m.right().Value() - m.right().Value());
326 : }
327 77294 : if (m.left().IsNaN()) { // NaN - x => NaN
328 : // Do some calculation to make a signalling NaN quiet.
329 1350 : return ReplaceFloat32(m.left().Value() - m.left().Value());
330 : }
331 75944 : if (m.IsFoldable()) { // L - R => (L - R)
332 75936 : return ReplaceFloat32(m.left().Value() - m.right().Value());
333 : }
334 8 : if (allow_signalling_nan_ && m.left().IsMinusZero()) {
335 : // -0.0 - round_down(-0.0 - R) => round_up(R)
336 1 : if (machine()->Float32RoundUp().IsSupported() &&
337 : m.right().IsFloat32RoundDown()) {
338 0 : if (m.right().InputAt(0)->opcode() == IrOpcode::kFloat32Sub) {
339 0 : Float32BinopMatcher mright0(m.right().InputAt(0));
340 0 : if (mright0.left().IsMinusZero()) {
341 : return Replace(graph()->NewNode(machine()->Float32RoundUp().op(),
342 0 : mright0.right().node()));
343 : }
344 : }
345 : }
346 : // -0.0 - R => -R
347 1 : node->RemoveInput(0);
348 1 : NodeProperties::ChangeOp(node, machine()->Float32Neg());
349 : return Changed(node);
350 : }
351 7 : break;
352 : }
353 : case IrOpcode::kFloat64Add: {
354 126268 : Float64BinopMatcher m(node);
355 126276 : if (m.right().IsNaN()) { // x + NaN => NaN
356 : // Do some calculation to make a signalling NaN quiet.
357 17589 : return ReplaceFloat64(m.right().Value() - m.right().Value());
358 : }
359 126229 : if (m.IsFoldable()) { // K + K => K
360 17495 : return ReplaceFloat64(m.left().Value() + m.right().Value());
361 : }
362 108734 : break;
363 : }
364 : case IrOpcode::kFloat64Sub: {
365 69260 : Float64BinopMatcher m(node);
366 139305 : if (allow_signalling_nan_ && m.right().Is(0) &&
367 785 : (Double(m.right().Value()).Sign() > 0)) {
368 32400 : return Replace(m.left().node()); // x - 0 => x
369 : }
370 68777 : if (m.right().IsNaN()) { // x - NaN => NaN
371 : // Do some calculation to make a signalling NaN quiet.
372 624 : return ReplaceFloat64(m.right().Value() - m.right().Value());
373 : }
374 68153 : if (m.left().IsNaN()) { // NaN - x => NaN
375 : // Do some calculation to make a signalling NaN quiet.
376 598 : return ReplaceFloat64(m.left().Value() - m.left().Value());
377 : }
378 67555 : if (m.IsFoldable()) { // L - R => (L - R)
379 22139 : return ReplaceFloat64(m.left().Value() - m.right().Value());
380 : }
381 45416 : if (allow_signalling_nan_ && m.left().IsMinusZero()) {
382 : // -0.0 - round_down(-0.0 - R) => round_up(R)
383 17111 : if (machine()->Float64RoundUp().IsSupported() &&
384 : m.right().IsFloat64RoundDown()) {
385 1260 : if (m.right().InputAt(0)->opcode() == IrOpcode::kFloat64Sub) {
386 0 : Float64BinopMatcher mright0(m.right().InputAt(0));
387 0 : if (mright0.left().IsMinusZero()) {
388 : return Replace(graph()->NewNode(machine()->Float64RoundUp().op(),
389 0 : mright0.right().node()));
390 : }
391 : }
392 : }
393 : // -0.0 - R => -R
394 8556 : node->RemoveInput(0);
395 8556 : NodeProperties::ChangeOp(node, machine()->Float64Neg());
396 : return Changed(node);
397 : }
398 36860 : break;
399 : }
400 : case IrOpcode::kFloat64Mul: {
401 26129 : Float64BinopMatcher m(node);
402 52257 : if (allow_signalling_nan_ && m.right().Is(1))
403 10884 : return Replace(m.left().node()); // x * 1.0 => x
404 26031 : if (m.right().Is(-1)) { // x * -1.0 => -0.0 - x
405 8750 : node->ReplaceInput(0, Float64Constant(-0.0));
406 8750 : node->ReplaceInput(1, m.left().node());
407 8750 : NodeProperties::ChangeOp(node, machine()->Float64Sub());
408 : return Changed(node);
409 : }
410 17281 : if (m.right().IsNaN()) { // x * NaN => NaN
411 : // Do some calculation to make a signalling NaN quiet.
412 33 : return ReplaceFloat64(m.right().Value() - m.right().Value());
413 : }
414 17248 : if (m.IsFoldable()) { // K * K => K
415 1801 : return ReplaceFloat64(m.left().Value() * m.right().Value());
416 : }
417 15447 : if (m.right().Is(2)) { // x * 2.0 => x + x
418 203 : node->ReplaceInput(1, m.left().node());
419 203 : NodeProperties::ChangeOp(node, machine()->Float64Add());
420 : return Changed(node);
421 : }
422 15244 : break;
423 : }
424 : case IrOpcode::kFloat64Div: {
425 30476 : Float64BinopMatcher m(node);
426 60952 : if (allow_signalling_nan_ && m.right().Is(1))
427 6778 : return Replace(m.left().node()); // x / 1.0 => x
428 : // TODO(ahaas): We could do x / 1.0 = x if we knew that x is not an sNaN.
429 30321 : if (m.right().IsNaN()) { // x / NaN => NaN
430 : // Do some calculation to make a signalling NaN quiet.
431 30 : return ReplaceFloat64(m.right().Value() - m.right().Value());
432 : }
433 30291 : if (m.left().IsNaN()) { // NaN / x => NaN
434 : // Do some calculation to make a signalling NaN quiet.
435 46 : return ReplaceFloat64(m.left().Value() - m.left().Value());
436 : }
437 30245 : if (m.IsFoldable()) { // K / K => K
438 3653 : return ReplaceFloat64(m.left().Value() / m.right().Value());
439 : }
440 53184 : if (allow_signalling_nan_ && m.right().Is(-1)) { // x / -1.0 => -x
441 40 : node->RemoveInput(1);
442 40 : NodeProperties::ChangeOp(node, machine()->Float64Neg());
443 : return Changed(node);
444 : }
445 26552 : if (m.right().IsNormal() && m.right().IsPositiveOrNegativePowerOf2()) {
446 : // All reciprocals of non-denormal powers of two can be represented
447 : // exactly, so division by power of two can be reduced to
448 : // multiplication by reciprocal, with the same result.
449 5708 : node->ReplaceInput(1, Float64Constant(1.0 / m.right().Value()));
450 2854 : NodeProperties::ChangeOp(node, machine()->Float64Mul());
451 : return Changed(node);
452 : }
453 23698 : break;
454 : }
455 : case IrOpcode::kFloat64Mod: {
456 2815 : Float64BinopMatcher m(node);
457 2815 : if (m.right().Is(0)) { // x % 0 => NaN
458 1256 : return ReplaceFloat64(std::numeric_limits<double>::quiet_NaN());
459 : }
460 2664 : if (m.right().IsNaN()) { // x % NaN => NaN
461 : return Replace(m.right().node());
462 : }
463 2627 : if (m.left().IsNaN()) { // NaN % x => NaN
464 : return Replace(m.left().node());
465 : }
466 2600 : if (m.IsFoldable()) { // K % K => K
467 1041 : return ReplaceFloat64(Modulo(m.left().Value(), m.right().Value()));
468 : }
469 1559 : break;
470 : }
471 : case IrOpcode::kFloat64Acos: {
472 : Float64Matcher m(node->InputAt(0));
473 102 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::acos(m.Value()));
474 : break;
475 : }
476 : case IrOpcode::kFloat64Acosh: {
477 : Float64Matcher m(node->InputAt(0));
478 100 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::acosh(m.Value()));
479 : break;
480 : }
481 : case IrOpcode::kFloat64Asin: {
482 : Float64Matcher m(node->InputAt(0));
483 102 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::asin(m.Value()));
484 : break;
485 : }
486 : case IrOpcode::kFloat64Asinh: {
487 : Float64Matcher m(node->InputAt(0));
488 100 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::asinh(m.Value()));
489 : break;
490 : }
491 : case IrOpcode::kFloat64Atan: {
492 : Float64Matcher m(node->InputAt(0));
493 121 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::atan(m.Value()));
494 : break;
495 : }
496 : case IrOpcode::kFloat64Atanh: {
497 : Float64Matcher m(node->InputAt(0));
498 100 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::atanh(m.Value()));
499 : break;
500 : }
501 : case IrOpcode::kFloat64Atan2: {
502 10049 : Float64BinopMatcher m(node);
503 10049 : if (m.right().IsNaN()) {
504 10008 : return Replace(m.right().node());
505 : }
506 10048 : if (m.left().IsNaN()) {
507 : return Replace(m.left().node());
508 : }
509 10047 : if (m.IsFoldable()) {
510 : return ReplaceFloat64(
511 10006 : base::ieee754::atan2(m.left().Value(), m.right().Value()));
512 : }
513 41 : break;
514 : }
515 : case IrOpcode::kFloat64Cbrt: {
516 : Float64Matcher m(node->InputAt(0));
517 0 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::cbrt(m.Value()));
518 : break;
519 : }
520 : case IrOpcode::kFloat64Cos: {
521 : Float64Matcher m(node->InputAt(0));
522 296 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::cos(m.Value()));
523 : break;
524 : }
525 : case IrOpcode::kFloat64Cosh: {
526 : Float64Matcher m(node->InputAt(0));
527 116 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::cosh(m.Value()));
528 : break;
529 : }
530 : case IrOpcode::kFloat64Exp: {
531 : Float64Matcher m(node->InputAt(0));
532 151 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::exp(m.Value()));
533 : break;
534 : }
535 : case IrOpcode::kFloat64Expm1: {
536 : Float64Matcher m(node->InputAt(0));
537 0 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::expm1(m.Value()));
538 : break;
539 : }
540 : case IrOpcode::kFloat64Log: {
541 : Float64Matcher m(node->InputAt(0));
542 443 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::log(m.Value()));
543 : break;
544 : }
545 : case IrOpcode::kFloat64Log1p: {
546 : Float64Matcher m(node->InputAt(0));
547 100 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::log1p(m.Value()));
548 : break;
549 : }
550 : case IrOpcode::kFloat64Log10: {
551 : Float64Matcher m(node->InputAt(0));
552 0 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::log10(m.Value()));
553 : break;
554 : }
555 : case IrOpcode::kFloat64Log2: {
556 : Float64Matcher m(node->InputAt(0));
557 0 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::log2(m.Value()));
558 : break;
559 : }
560 : case IrOpcode::kFloat64Pow: {
561 11042 : Float64BinopMatcher m(node);
562 11042 : if (m.IsFoldable()) {
563 21722 : return ReplaceFloat64(Pow(m.left().Value(), m.right().Value()));
564 182 : } else if (m.right().Is(0.0)) { // x ** +-0.0 => 1.0
565 : return ReplaceFloat64(1.0);
566 180 : } else if (m.right().Is(-2.0)) { // x ** -2.0 => 1 / (x * x)
567 0 : node->ReplaceInput(0, Float64Constant(1.0));
568 0 : node->ReplaceInput(1, Float64Mul(m.left().node(), m.left().node()));
569 0 : NodeProperties::ChangeOp(node, machine()->Float64Div());
570 : return Changed(node);
571 180 : } else if (m.right().Is(2.0)) { // x ** 2.0 => x * x
572 0 : node->ReplaceInput(1, m.left().node());
573 0 : NodeProperties::ChangeOp(node, machine()->Float64Mul());
574 : return Changed(node);
575 180 : } else if (m.right().Is(-0.5)) {
576 : // x ** 0.5 => 1 / (if x <= -Infinity then Infinity else sqrt(0.0 + x))
577 0 : node->ReplaceInput(0, Float64Constant(1.0));
578 0 : node->ReplaceInput(1, Float64PowHalf(m.left().node()));
579 0 : NodeProperties::ChangeOp(node, machine()->Float64Div());
580 : return Changed(node);
581 180 : } else if (m.right().Is(0.5)) {
582 : // x ** 0.5 => if x <= -Infinity then Infinity else sqrt(0.0 + x)
583 0 : return Replace(Float64PowHalf(m.left().node()));
584 : }
585 180 : break;
586 : }
587 : case IrOpcode::kFloat64Sin: {
588 : Float64Matcher m(node->InputAt(0));
589 321 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::sin(m.Value()));
590 : break;
591 : }
592 : case IrOpcode::kFloat64Sinh: {
593 : Float64Matcher m(node->InputAt(0));
594 116 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::sinh(m.Value()));
595 : break;
596 : }
597 : case IrOpcode::kFloat64Tan: {
598 : Float64Matcher m(node->InputAt(0));
599 121 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::tan(m.Value()));
600 : break;
601 : }
602 : case IrOpcode::kFloat64Tanh: {
603 : Float64Matcher m(node->InputAt(0));
604 116 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::tanh(m.Value()));
605 : break;
606 : }
607 : case IrOpcode::kChangeFloat32ToFloat64: {
608 : Float32Matcher m(node->InputAt(0));
609 12162 : if (m.HasValue()) {
610 174 : if (!allow_signalling_nan_ && std::isnan(m.Value())) {
611 : // Do some calculation to make guarantee the value is a quiet NaN.
612 0 : return ReplaceFloat64(m.Value() + m.Value());
613 : }
614 174 : return ReplaceFloat64(m.Value());
615 : }
616 : break;
617 : }
618 : case IrOpcode::kChangeFloat64ToInt32: {
619 : Float64Matcher m(node->InputAt(0));
620 13921 : if (m.HasValue()) return ReplaceInt32(FastD2I(m.Value()));
621 8562 : if (m.IsChangeInt32ToFloat64()) return Replace(m.node()->InputAt(0));
622 : break;
623 : }
624 : case IrOpcode::kChangeFloat64ToUint32: {
625 : Float64Matcher m(node->InputAt(0));
626 392 : if (m.HasValue()) return ReplaceInt32(FastD2UI(m.Value()));
627 278 : if (m.IsChangeUint32ToFloat64()) return Replace(m.node()->InputAt(0));
628 : break;
629 : }
630 : case IrOpcode::kChangeInt32ToFloat64: {
631 : Int32Matcher m(node->InputAt(0));
632 197733 : if (m.HasValue()) return ReplaceFloat64(FastI2D(m.Value()));
633 : break;
634 : }
635 : case IrOpcode::kChangeInt32ToInt64: {
636 : Int32Matcher m(node->InputAt(0));
637 228244 : if (m.HasValue()) return ReplaceInt64(m.Value());
638 : break;
639 : }
640 : case IrOpcode::kChangeUint32ToFloat64: {
641 : Uint32Matcher m(node->InputAt(0));
642 2008 : if (m.HasValue()) return ReplaceFloat64(FastUI2D(m.Value()));
643 : break;
644 : }
645 : case IrOpcode::kChangeUint32ToUint64: {
646 : Uint32Matcher m(node->InputAt(0));
647 225217 : if (m.HasValue()) return ReplaceInt64(static_cast<uint64_t>(m.Value()));
648 : break;
649 : }
650 : case IrOpcode::kTruncateFloat64ToWord32: {
651 : Float64Matcher m(node->InputAt(0));
652 14512 : if (m.HasValue()) return ReplaceInt32(DoubleToInt32(m.Value()));
653 11012 : if (m.IsChangeInt32ToFloat64()) return Replace(m.node()->InputAt(0));
654 : return NoChange();
655 : }
656 : case IrOpcode::kTruncateInt64ToInt32: {
657 : Int64Matcher m(node->InputAt(0));
658 159685 : if (m.HasValue()) return ReplaceInt32(static_cast<int32_t>(m.Value()));
659 159577 : if (m.IsChangeInt32ToInt64()) return Replace(m.node()->InputAt(0));
660 : break;
661 : }
662 : case IrOpcode::kTruncateFloat64ToFloat32: {
663 : Float64Matcher m(node->InputAt(0));
664 6902 : if (m.HasValue()) {
665 912 : if (!allow_signalling_nan_ && std::isnan(m.Value())) {
666 : // Do some calculation to make guarantee the value is a quiet NaN.
667 0 : return ReplaceFloat32(DoubleToFloat32(m.Value() + m.Value()));
668 : }
669 : return ReplaceFloat32(DoubleToFloat32(m.Value()));
670 : }
671 5990 : if (allow_signalling_nan_ && m.IsChangeFloat32ToFloat64())
672 : return Replace(m.node()->InputAt(0));
673 : break;
674 : }
675 : case IrOpcode::kRoundFloat64ToInt32: {
676 : Float64Matcher m(node->InputAt(0));
677 47857 : if (m.HasValue()) return ReplaceInt32(static_cast<int32_t>(m.Value()));
678 47545 : if (m.IsChangeInt32ToFloat64()) return Replace(m.node()->InputAt(0));
679 : break;
680 : }
681 : case IrOpcode::kFloat64InsertLowWord32:
682 4800 : return ReduceFloat64InsertLowWord32(node);
683 : case IrOpcode::kFloat64InsertHighWord32:
684 4800 : return ReduceFloat64InsertHighWord32(node);
685 : case IrOpcode::kStore:
686 : case IrOpcode::kUnalignedStore:
687 : case IrOpcode::kCheckedStore:
688 1525464 : return ReduceStore(node);
689 : case IrOpcode::kFloat64Equal:
690 : case IrOpcode::kFloat64LessThan:
691 : case IrOpcode::kFloat64LessThanOrEqual:
692 167910 : return ReduceFloat64Compare(node);
693 : case IrOpcode::kFloat64RoundDown:
694 18166 : return ReduceFloat64RoundDown(node);
695 : default:
696 : break;
697 : }
698 : return NoChange();
699 : }
700 :
701 512091 : Reduction MachineOperatorReducer::ReduceInt32Add(Node* node) {
702 : DCHECK_EQ(IrOpcode::kInt32Add, node->opcode());
703 512091 : Int32BinopMatcher m(node);
704 512092 : if (m.right().Is(0)) return Replace(m.left().node()); // x + 0 => x
705 484859 : if (m.IsFoldable()) { // K + K => K
706 : return ReplaceUint32(bit_cast<uint32_t>(m.left().Value()) +
707 38569 : bit_cast<uint32_t>(m.right().Value()));
708 : }
709 446290 : if (m.left().IsInt32Sub()) {
710 1414 : Int32BinopMatcher mleft(m.left().node());
711 1414 : if (mleft.left().Is(0)) { // (0 - x) + y => y - x
712 13 : node->ReplaceInput(0, m.right().node());
713 13 : node->ReplaceInput(1, mleft.right().node());
714 13 : NodeProperties::ChangeOp(node, machine()->Int32Sub());
715 13 : Reduction const reduction = ReduceInt32Sub(node);
716 13 : return reduction.Changed() ? reduction : Changed(node);
717 : }
718 : }
719 446277 : if (m.right().IsInt32Sub()) {
720 618 : Int32BinopMatcher mright(m.right().node());
721 618 : if (mright.left().Is(0)) { // y + (0 - x) => y - x
722 54 : node->ReplaceInput(1, mright.right().node());
723 54 : NodeProperties::ChangeOp(node, machine()->Int32Sub());
724 54 : Reduction const reduction = ReduceInt32Sub(node);
725 54 : return reduction.Changed() ? reduction : Changed(node);
726 : }
727 : }
728 : return NoChange();
729 : }
730 :
731 738261 : Reduction MachineOperatorReducer::ReduceInt64Add(Node* node) {
732 : DCHECK_EQ(IrOpcode::kInt64Add, node->opcode());
733 738261 : Int64BinopMatcher m(node);
734 738261 : if (m.right().Is(0)) return Replace(m.left().node()); // x + 0 => 0
735 737277 : if (m.IsFoldable()) {
736 : return Replace(Uint64Constant(bit_cast<uint64_t>(m.left().Value()) +
737 79934 : bit_cast<uint64_t>(m.right().Value())));
738 : }
739 : return NoChange();
740 : }
741 :
742 66714 : Reduction MachineOperatorReducer::ReduceInt32Sub(Node* node) {
743 : DCHECK_EQ(IrOpcode::kInt32Sub, node->opcode());
744 66714 : Int32BinopMatcher m(node);
745 66715 : if (m.right().Is(0)) return Replace(m.left().node()); // x - 0 => x
746 66021 : if (m.IsFoldable()) { // K - K => K
747 30291 : return ReplaceInt32(static_cast<uint32_t>(m.left().Value()) -
748 30291 : static_cast<uint32_t>(m.right().Value()));
749 : }
750 35730 : if (m.LeftEqualsRight()) return ReplaceInt32(0); // x - x => 0
751 35728 : if (m.right().HasValue()) { // x - K => x + -K
752 27540 : node->ReplaceInput(1, Int32Constant(-m.right().Value()));
753 13770 : NodeProperties::ChangeOp(node, machine()->Int32Add());
754 13770 : Reduction const reduction = ReduceInt32Add(node);
755 13770 : return reduction.Changed() ? reduction : Changed(node);
756 : }
757 : return NoChange();
758 : }
759 :
760 161572 : Reduction MachineOperatorReducer::ReduceInt64Sub(Node* node) {
761 : DCHECK_EQ(IrOpcode::kInt64Sub, node->opcode());
762 161572 : Int64BinopMatcher m(node);
763 161571 : if (m.right().Is(0)) return Replace(m.left().node()); // x - 0 => x
764 160593 : if (m.IsFoldable()) { // K - K => K
765 : return Replace(Uint64Constant(bit_cast<uint64_t>(m.left().Value()) -
766 38394 : bit_cast<uint64_t>(m.right().Value())));
767 : }
768 122199 : if (m.LeftEqualsRight()) return Replace(Int64Constant(0)); // x - x => 0
769 122193 : if (m.right().HasValue()) { // x - K => x + -K
770 117720 : node->ReplaceInput(1, Int64Constant(-m.right().Value()));
771 117722 : NodeProperties::ChangeOp(node, machine()->Int64Add());
772 117721 : Reduction const reduction = ReduceInt64Add(node);
773 117721 : return reduction.Changed() ? reduction : Changed(node);
774 : }
775 : return NoChange();
776 : }
777 :
778 23532 : Reduction MachineOperatorReducer::ReduceInt32Div(Node* node) {
779 23532 : Int32BinopMatcher m(node);
780 23532 : if (m.left().Is(0)) return Replace(m.left().node()); // 0 / x => 0
781 23181 : if (m.right().Is(0)) return Replace(m.right().node()); // x / 0 => 0
782 23180 : if (m.right().Is(1)) return Replace(m.left().node()); // x / 1 => x
783 22783 : if (m.IsFoldable()) { // K / K => K
784 : return ReplaceInt32(
785 19206 : base::bits::SignedDiv32(m.left().Value(), m.right().Value()));
786 : }
787 3577 : if (m.LeftEqualsRight()) { // x / x => x != 0
788 : Node* const zero = Int32Constant(0);
789 5 : return Replace(Word32Equal(Word32Equal(m.left().node(), zero), zero));
790 : }
791 3572 : if (m.right().Is(-1)) { // x / -1 => 0 - x
792 34 : node->ReplaceInput(0, Int32Constant(0));
793 34 : node->ReplaceInput(1, m.left().node());
794 34 : node->TrimInputCount(2);
795 34 : NodeProperties::ChangeOp(node, machine()->Int32Sub());
796 : return Changed(node);
797 : }
798 3538 : if (m.right().HasValue()) {
799 3019 : int32_t const divisor = m.right().Value();
800 : Node* const dividend = m.left().node();
801 : Node* quotient = dividend;
802 3019 : if (base::bits::IsPowerOfTwo(Abs(divisor))) {
803 882 : uint32_t const shift = WhichPowerOf2(Abs(divisor));
804 : DCHECK_NE(0u, shift);
805 882 : if (shift > 1) {
806 699 : quotient = Word32Sar(quotient, 31);
807 : }
808 882 : quotient = Int32Add(Word32Shr(quotient, 32u - shift), dividend);
809 882 : quotient = Word32Sar(quotient, shift);
810 : } else {
811 2137 : quotient = Int32Div(quotient, Abs(divisor));
812 : }
813 3019 : if (divisor < 0) {
814 1297 : node->ReplaceInput(0, Int32Constant(0));
815 1297 : node->ReplaceInput(1, quotient);
816 1297 : node->TrimInputCount(2);
817 1297 : NodeProperties::ChangeOp(node, machine()->Int32Sub());
818 : return Changed(node);
819 : }
820 : return Replace(quotient);
821 : }
822 : return NoChange();
823 : }
824 :
825 :
826 22741 : Reduction MachineOperatorReducer::ReduceUint32Div(Node* node) {
827 22741 : Uint32BinopMatcher m(node);
828 22741 : if (m.left().Is(0)) return Replace(m.left().node()); // 0 / x => 0
829 22329 : if (m.right().Is(0)) return Replace(m.right().node()); // x / 0 => 0
830 22281 : if (m.right().Is(1)) return Replace(m.left().node()); // x / 1 => x
831 21878 : if (m.IsFoldable()) { // K / K => K
832 : return ReplaceUint32(
833 21340 : base::bits::UnsignedDiv32(m.left().Value(), m.right().Value()));
834 : }
835 538 : if (m.LeftEqualsRight()) { // x / x => x != 0
836 : Node* const zero = Int32Constant(0);
837 1 : return Replace(Word32Equal(Word32Equal(m.left().node(), zero), zero));
838 : }
839 537 : if (m.right().HasValue()) {
840 : Node* const dividend = m.left().node();
841 366 : uint32_t const divisor = m.right().Value();
842 366 : if (base::bits::IsPowerOfTwo(divisor)) { // x / 2^n => x >> n
843 574 : node->ReplaceInput(1, Uint32Constant(WhichPowerOf2(m.right().Value())));
844 287 : node->TrimInputCount(2);
845 287 : NodeProperties::ChangeOp(node, machine()->Word32Shr());
846 : return Changed(node);
847 : } else {
848 79 : return Replace(Uint32Div(dividend, divisor));
849 : }
850 : }
851 : return NoChange();
852 : }
853 :
854 :
855 34882 : Reduction MachineOperatorReducer::ReduceInt32Mod(Node* node) {
856 34882 : Int32BinopMatcher m(node);
857 34882 : if (m.left().Is(0)) return Replace(m.left().node()); // 0 % x => 0
858 34422 : if (m.right().Is(0)) return Replace(m.right().node()); // x % 0 => 0
859 34322 : if (m.right().Is(1)) return ReplaceInt32(0); // x % 1 => 0
860 33947 : if (m.right().Is(-1)) return ReplaceInt32(0); // x % -1 => 0
861 33604 : if (m.LeftEqualsRight()) return ReplaceInt32(0); // x % x => 0
862 33593 : if (m.IsFoldable()) { // K % K => K
863 : return ReplaceInt32(
864 28697 : base::bits::SignedMod32(m.left().Value(), m.right().Value()));
865 : }
866 4896 : if (m.right().HasValue()) {
867 : Node* const dividend = m.left().node();
868 4225 : uint32_t const divisor = Abs(m.right().Value());
869 4225 : if (base::bits::IsPowerOfTwo(divisor)) {
870 1114 : uint32_t const mask = divisor - 1;
871 : Node* const zero = Int32Constant(0);
872 : Diamond d(graph(), common(),
873 : graph()->NewNode(machine()->Int32LessThan(), dividend, zero),
874 2228 : BranchHint::kFalse);
875 : return Replace(
876 : d.Phi(MachineRepresentation::kWord32,
877 : Int32Sub(zero, Word32And(Int32Sub(zero, dividend), mask)),
878 1114 : Word32And(dividend, mask)));
879 : } else {
880 3111 : Node* quotient = Int32Div(dividend, divisor);
881 : DCHECK_EQ(dividend, node->InputAt(0));
882 3111 : node->ReplaceInput(1, Int32Mul(quotient, Int32Constant(divisor)));
883 3111 : node->TrimInputCount(2);
884 3111 : NodeProperties::ChangeOp(node, machine()->Int32Sub());
885 : }
886 : return Changed(node);
887 : }
888 : return NoChange();
889 : }
890 :
891 :
892 22928 : Reduction MachineOperatorReducer::ReduceUint32Mod(Node* node) {
893 22928 : Uint32BinopMatcher m(node);
894 22928 : if (m.left().Is(0)) return Replace(m.left().node()); // 0 % x => 0
895 22482 : if (m.right().Is(0)) return Replace(m.right().node()); // x % 0 => 0
896 22434 : if (m.right().Is(1)) return ReplaceUint32(0); // x % 1 => 0
897 22031 : if (m.LeftEqualsRight()) return ReplaceInt32(0); // x % x => 0
898 22029 : if (m.IsFoldable()) { // K % K => K
899 : return ReplaceUint32(
900 21382 : base::bits::UnsignedMod32(m.left().Value(), m.right().Value()));
901 : }
902 647 : if (m.right().HasValue()) {
903 : Node* const dividend = m.left().node();
904 511 : uint32_t const divisor = m.right().Value();
905 511 : if (base::bits::IsPowerOfTwo(divisor)) { // x % 2^n => x & 2^n-1
906 540 : node->ReplaceInput(1, Uint32Constant(m.right().Value() - 1));
907 270 : node->TrimInputCount(2);
908 270 : NodeProperties::ChangeOp(node, machine()->Word32And());
909 : } else {
910 241 : Node* quotient = Uint32Div(dividend, divisor);
911 : DCHECK_EQ(dividend, node->InputAt(0));
912 241 : node->ReplaceInput(1, Int32Mul(quotient, Uint32Constant(divisor)));
913 241 : node->TrimInputCount(2);
914 241 : NodeProperties::ChangeOp(node, machine()->Int32Sub());
915 : }
916 : return Changed(node);
917 : }
918 : return NoChange();
919 : }
920 :
921 :
922 1525464 : Reduction MachineOperatorReducer::ReduceStore(Node* node) {
923 : NodeMatcher nm(node);
924 : MachineRepresentation rep;
925 : int value_input;
926 1525464 : if (nm.IsCheckedStore()) {
927 55186 : rep = CheckedStoreRepresentationOf(node->op());
928 : value_input = 3;
929 1470278 : } else if (nm.IsStore()) {
930 1470278 : rep = StoreRepresentationOf(node->op()).representation();
931 : value_input = 2;
932 : } else {
933 : DCHECK(nm.IsUnalignedStore());
934 0 : rep = UnalignedStoreRepresentationOf(node->op());
935 : value_input = 2;
936 : }
937 :
938 1525464 : Node* const value = node->InputAt(value_input);
939 :
940 1525464 : switch (value->opcode()) {
941 : case IrOpcode::kWord32And: {
942 1837 : Uint32BinopMatcher m(value);
943 4268 : if (m.right().HasValue() && ((rep == MachineRepresentation::kWord8 &&
944 1475 : (m.right().Value() & 0xff) == 0xff) ||
945 244 : (rep == MachineRepresentation::kWord16 &&
946 244 : (m.right().Value() & 0xffff) == 0xffff))) {
947 653 : node->ReplaceInput(value_input, m.left().node());
948 653 : return Changed(node);
949 : }
950 1184 : break;
951 : }
952 : case IrOpcode::kWord32Sar: {
953 485 : Int32BinopMatcher m(value);
954 1141 : if (m.left().IsWord32Shl() && ((rep == MachineRepresentation::kWord8 &&
955 268 : m.right().IsInRange(1, 24)) ||
956 259 : (rep == MachineRepresentation::kWord16 &&
957 : m.right().IsInRange(1, 16)))) {
958 430 : Int32BinopMatcher mleft(m.left().node());
959 430 : if (mleft.right().Is(m.right().Value())) {
960 430 : node->ReplaceInput(value_input, mleft.left().node());
961 430 : return Changed(node);
962 : }
963 : }
964 55 : break;
965 : }
966 : default:
967 : break;
968 : }
969 : return NoChange();
970 : }
971 :
972 :
973 256815 : Reduction MachineOperatorReducer::ReduceProjection(size_t index, Node* node) {
974 256815 : switch (node->opcode()) {
975 : case IrOpcode::kInt32AddWithOverflow: {
976 : DCHECK(index == 0 || index == 1);
977 111785 : Int32BinopMatcher m(node);
978 111786 : if (m.IsFoldable()) {
979 : int32_t val;
980 : bool ovf = base::bits::SignedAddOverflow32(m.left().Value(),
981 20016 : m.right().Value(), &val);
982 20016 : return ReplaceInt32(index == 0 ? val : ovf);
983 : }
984 91770 : if (m.right().Is(0)) {
985 32 : return Replace(index == 0 ? m.left().node() : m.right().node());
986 : }
987 91738 : break;
988 : }
989 : case IrOpcode::kInt32SubWithOverflow: {
990 : DCHECK(index == 0 || index == 1);
991 116966 : Int32BinopMatcher m(node);
992 116966 : if (m.IsFoldable()) {
993 : int32_t val;
994 : bool ovf = base::bits::SignedSubOverflow32(m.left().Value(),
995 20042 : m.right().Value(), &val);
996 20042 : return ReplaceInt32(index == 0 ? val : ovf);
997 : }
998 96924 : if (m.right().Is(0)) {
999 2 : return Replace(index == 0 ? m.left().node() : m.right().node());
1000 : }
1001 96922 : break;
1002 : }
1003 : case IrOpcode::kInt32MulWithOverflow: {
1004 : DCHECK(index == 0 || index == 1);
1005 26354 : Int32BinopMatcher m(node);
1006 26354 : if (m.IsFoldable()) {
1007 : int32_t val;
1008 : bool ovf = base::bits::SignedMulOverflow32(m.left().Value(),
1009 20316 : m.right().Value(), &val);
1010 20316 : return ReplaceInt32(index == 0 ? val : ovf);
1011 : }
1012 6038 : if (m.right().Is(0)) {
1013 : return Replace(m.right().node());
1014 : }
1015 5962 : if (m.right().Is(1)) {
1016 76 : return index == 0 ? Replace(m.left().node()) : ReplaceInt32(0);
1017 : }
1018 5886 : break;
1019 : }
1020 : default:
1021 : break;
1022 : }
1023 : return NoChange();
1024 : }
1025 :
1026 :
1027 65395 : Reduction MachineOperatorReducer::ReduceWord32Shifts(Node* node) {
1028 : DCHECK((node->opcode() == IrOpcode::kWord32Shl) ||
1029 : (node->opcode() == IrOpcode::kWord32Shr) ||
1030 : (node->opcode() == IrOpcode::kWord32Sar));
1031 65395 : if (machine()->Word32ShiftIsSafe()) {
1032 : // Remove the explicit 'and' with 0x1f if the shift provided by the machine
1033 : // instruction matches that required by JavaScript.
1034 65017 : Int32BinopMatcher m(node);
1035 65017 : if (m.right().IsWord32And()) {
1036 2453 : Int32BinopMatcher mright(m.right().node());
1037 2453 : if (mright.right().Is(0x1f)) {
1038 1075 : node->ReplaceInput(1, mright.left().node());
1039 1075 : return Changed(node);
1040 : }
1041 : }
1042 : }
1043 : return NoChange();
1044 : }
1045 :
1046 :
1047 40321 : Reduction MachineOperatorReducer::ReduceWord32Shl(Node* node) {
1048 : DCHECK_EQ(IrOpcode::kWord32Shl, node->opcode());
1049 40321 : Int32BinopMatcher m(node);
1050 40321 : if (m.right().Is(0)) return Replace(m.left().node()); // x << 0 => x
1051 39530 : if (m.IsFoldable()) { // K << K => K
1052 11997 : return ReplaceInt32(m.left().Value() << m.right().Value());
1053 : }
1054 27533 : if (m.right().IsInRange(1, 31)) {
1055 : // (x >>> K) << K => x & ~(2^K - 1)
1056 : // (x >> K) << K => x & ~(2^K - 1)
1057 23726 : if (m.left().IsWord32Sar() || m.left().IsWord32Shr()) {
1058 4207 : Int32BinopMatcher mleft(m.left().node());
1059 4207 : if (mleft.right().Is(m.right().Value())) {
1060 3233 : node->ReplaceInput(0, mleft.left().node());
1061 : node->ReplaceInput(1,
1062 6466 : Uint32Constant(~((1U << m.right().Value()) - 1U)));
1063 3233 : NodeProperties::ChangeOp(node, machine()->Word32And());
1064 3233 : Reduction reduction = ReduceWord32And(node);
1065 3233 : return reduction.Changed() ? reduction : Changed(node);
1066 : }
1067 : }
1068 : }
1069 24300 : return ReduceWord32Shifts(node);
1070 : }
1071 :
1072 217351 : Reduction MachineOperatorReducer::ReduceWord64Shl(Node* node) {
1073 : DCHECK_EQ(IrOpcode::kWord64Shl, node->opcode());
1074 217351 : Int64BinopMatcher m(node);
1075 217352 : if (m.right().Is(0)) return Replace(m.left().node()); // x << 0 => x
1076 216860 : if (m.IsFoldable()) { // K << K => K
1077 76385 : return ReplaceInt64(m.left().Value() << m.right().Value());
1078 : }
1079 : return NoChange();
1080 : }
1081 :
1082 47454 : Reduction MachineOperatorReducer::ReduceWord32Shr(Node* node) {
1083 47454 : Uint32BinopMatcher m(node);
1084 47454 : if (m.right().Is(0)) return Replace(m.left().node()); // x >>> 0 => x
1085 29921 : if (m.IsFoldable()) { // K >>> K => K
1086 11758 : return ReplaceInt32(m.left().Value() >> m.right().Value());
1087 : }
1088 18163 : if (m.left().IsWord32And() && m.right().HasValue()) {
1089 261 : Uint32BinopMatcher mleft(m.left().node());
1090 261 : if (mleft.right().HasValue()) {
1091 258 : uint32_t shift = m.right().Value() & 0x1f;
1092 258 : uint32_t mask = mleft.right().Value();
1093 258 : if ((mask >> shift) == 0) {
1094 : // (m >>> s) == 0 implies ((x & m) >>> s) == 0
1095 31 : return ReplaceInt32(0);
1096 : }
1097 : }
1098 : }
1099 18132 : return ReduceWord32Shifts(node);
1100 : }
1101 :
1102 31116 : Reduction MachineOperatorReducer::ReduceWord64Shr(Node* node) {
1103 : DCHECK_EQ(IrOpcode::kWord64Shr, node->opcode());
1104 31116 : Uint64BinopMatcher m(node);
1105 31116 : if (m.right().Is(0)) return Replace(m.left().node()); // x >>> 0 => x
1106 30624 : if (m.IsFoldable()) { // K >> K => K
1107 30618 : return ReplaceInt64(m.left().Value() >> m.right().Value());
1108 : }
1109 : return NoChange();
1110 : }
1111 :
1112 35950 : Reduction MachineOperatorReducer::ReduceWord32Sar(Node* node) {
1113 35950 : Int32BinopMatcher m(node);
1114 35950 : if (m.right().Is(0)) return Replace(m.left().node()); // x >> 0 => x
1115 35059 : if (m.IsFoldable()) { // K >> K => K
1116 12033 : return ReplaceInt32(m.left().Value() >> m.right().Value());
1117 : }
1118 23026 : if (m.left().IsWord32Shl()) {
1119 1651 : Int32BinopMatcher mleft(m.left().node());
1120 1651 : if (mleft.left().IsComparison()) {
1121 122 : if (m.right().Is(31) && mleft.right().Is(31)) {
1122 : // Comparison << 31 >> 31 => 0 - Comparison
1123 61 : node->ReplaceInput(0, Int32Constant(0));
1124 61 : node->ReplaceInput(1, mleft.left().node());
1125 61 : NodeProperties::ChangeOp(node, machine()->Int32Sub());
1126 61 : Reduction const reduction = ReduceInt32Sub(node);
1127 61 : return reduction.Changed() ? reduction : Changed(node);
1128 : }
1129 1590 : } else if (mleft.left().IsLoad()) {
1130 : LoadRepresentation const rep =
1131 2 : LoadRepresentationOf(mleft.left().node()->op());
1132 4 : if (m.right().Is(24) && mleft.right().Is(24) &&
1133 : rep == MachineType::Int8()) {
1134 : // Load[kMachInt8] << 24 >> 24 => Load[kMachInt8]
1135 : return Replace(mleft.left().node());
1136 : }
1137 3 : if (m.right().Is(16) && mleft.right().Is(16) &&
1138 : rep == MachineType::Int16()) {
1139 : // Load[kMachInt16] << 16 >> 16 => Load[kMachInt8]
1140 : return Replace(mleft.left().node());
1141 : }
1142 : }
1143 : }
1144 22963 : return ReduceWord32Shifts(node);
1145 : }
1146 :
1147 197762 : Reduction MachineOperatorReducer::ReduceWord64Sar(Node* node) {
1148 197762 : Int64BinopMatcher m(node);
1149 197762 : if (m.right().Is(0)) return Replace(m.left().node()); // x >> 0 => x
1150 197270 : if (m.IsFoldable()) {
1151 30626 : return ReplaceInt64(m.left().Value() >> m.right().Value());
1152 : }
1153 : return NoChange();
1154 : }
1155 :
1156 520904 : Reduction MachineOperatorReducer::ReduceWord32And(Node* node) {
1157 : DCHECK_EQ(IrOpcode::kWord32And, node->opcode());
1158 520904 : Int32BinopMatcher m(node);
1159 520904 : if (m.right().Is(0)) return Replace(m.right().node()); // x & 0 => 0
1160 518943 : if (m.right().Is(-1)) return Replace(m.left().node()); // x & -1 => x
1161 520637 : if (m.left().IsComparison() && m.right().Is(1)) { // CMP & 1 => CMP
1162 : return Replace(m.left().node());
1163 : }
1164 518231 : if (m.IsFoldable()) { // K & K => K
1165 33234 : return ReplaceInt32(m.left().Value() & m.right().Value());
1166 : }
1167 484997 : if (m.LeftEqualsRight()) return Replace(m.left().node()); // x & x => x
1168 484974 : if (m.left().IsWord32And() && m.right().HasValue()) {
1169 19762 : Int32BinopMatcher mleft(m.left().node());
1170 19762 : if (mleft.right().HasValue()) { // (x & K) & K => x & K
1171 19746 : node->ReplaceInput(0, mleft.left().node());
1172 : node->ReplaceInput(
1173 39492 : 1, Int32Constant(m.right().Value() & mleft.right().Value()));
1174 19746 : Reduction const reduction = ReduceWord32And(node);
1175 19746 : return reduction.Changed() ? reduction : Changed(node);
1176 : }
1177 : }
1178 465228 : if (m.right().IsNegativePowerOf2()) {
1179 328424 : int32_t const mask = m.right().Value();
1180 328424 : if (m.left().IsWord32Shl()) {
1181 2578 : Uint32BinopMatcher mleft(m.left().node());
1182 5156 : if (mleft.right().HasValue() &&
1183 2578 : (mleft.right().Value() & 0x1f) >=
1184 2578 : base::bits::CountTrailingZeros32(mask)) {
1185 : // (x << L) & (-1 << K) => x << L iff L >= K
1186 2576 : return Replace(mleft.node());
1187 : }
1188 325846 : } else if (m.left().IsInt32Add()) {
1189 123584 : Int32BinopMatcher mleft(m.left().node());
1190 221577 : if (mleft.right().HasValue() &&
1191 97993 : (mleft.right().Value() & mask) == mleft.right().Value()) {
1192 : // (x + (K << L)) & (-1 << L) => (x & (-1 << L)) + (K << L)
1193 97758 : node->ReplaceInput(0, Word32And(mleft.left().node(), m.right().node()));
1194 97758 : node->ReplaceInput(1, mleft.right().node());
1195 97758 : NodeProperties::ChangeOp(node, machine()->Int32Add());
1196 97758 : Reduction const reduction = ReduceInt32Add(node);
1197 97758 : return reduction.Changed() ? reduction : Changed(node);
1198 : }
1199 25826 : if (mleft.left().IsInt32Mul()) {
1200 2924 : Int32BinopMatcher mleftleft(mleft.left().node());
1201 5848 : if (mleftleft.right().IsMultipleOf(-mask)) {
1202 : // (y * (K << L) + x) & (-1 << L) => (x & (-1 << L)) + y * (K << L)
1203 : node->ReplaceInput(0,
1204 2923 : Word32And(mleft.right().node(), m.right().node()));
1205 2923 : node->ReplaceInput(1, mleftleft.node());
1206 2923 : NodeProperties::ChangeOp(node, machine()->Int32Add());
1207 2923 : Reduction const reduction = ReduceInt32Add(node);
1208 2923 : return reduction.Changed() ? reduction : Changed(node);
1209 : }
1210 : }
1211 22903 : if (mleft.right().IsInt32Mul()) {
1212 8797 : Int32BinopMatcher mleftright(mleft.right().node());
1213 17594 : if (mleftright.right().IsMultipleOf(-mask)) {
1214 : // (x + y * (K << L)) & (-1 << L) => (x & (-1 << L)) + y * (K << L)
1215 : node->ReplaceInput(0,
1216 8783 : Word32And(mleft.left().node(), m.right().node()));
1217 8783 : node->ReplaceInput(1, mleftright.node());
1218 8783 : NodeProperties::ChangeOp(node, machine()->Int32Add());
1219 8783 : Reduction const reduction = ReduceInt32Add(node);
1220 8783 : return reduction.Changed() ? reduction : Changed(node);
1221 : }
1222 : }
1223 14120 : if (mleft.left().IsWord32Shl()) {
1224 38 : Int32BinopMatcher mleftleft(mleft.left().node());
1225 114 : if (mleftleft.right().Is(base::bits::CountTrailingZeros32(mask))) {
1226 : // (y << L + x) & (-1 << L) => (x & (-1 << L)) + y << L
1227 : node->ReplaceInput(0,
1228 31 : Word32And(mleft.right().node(), m.right().node()));
1229 31 : node->ReplaceInput(1, mleftleft.node());
1230 31 : NodeProperties::ChangeOp(node, machine()->Int32Add());
1231 31 : Reduction const reduction = ReduceInt32Add(node);
1232 31 : return reduction.Changed() ? reduction : Changed(node);
1233 : }
1234 : }
1235 14089 : if (mleft.right().IsWord32Shl()) {
1236 8645 : Int32BinopMatcher mleftright(mleft.right().node());
1237 25935 : if (mleftright.right().Is(base::bits::CountTrailingZeros32(mask))) {
1238 : // (x + y << L) & (-1 << L) => (x & (-1 << L)) + y << L
1239 : node->ReplaceInput(0,
1240 3287 : Word32And(mleft.left().node(), m.right().node()));
1241 3287 : node->ReplaceInput(1, mleftright.node());
1242 3287 : NodeProperties::ChangeOp(node, machine()->Int32Add());
1243 3287 : Reduction const reduction = ReduceInt32Add(node);
1244 3287 : return reduction.Changed() ? reduction : Changed(node);
1245 : }
1246 : }
1247 202262 : } else if (m.left().IsInt32Mul()) {
1248 5953 : Int32BinopMatcher mleft(m.left().node());
1249 11906 : if (mleft.right().IsMultipleOf(-mask)) {
1250 : // (x * (K << L)) & (-1 << L) => x * (K << L)
1251 5904 : return Replace(mleft.node());
1252 : }
1253 : }
1254 : }
1255 : return NoChange();
1256 : }
1257 :
1258 19204 : Reduction MachineOperatorReducer::TryMatchWord32Ror(Node* node) {
1259 : DCHECK(IrOpcode::kWord32Or == node->opcode() ||
1260 : IrOpcode::kWord32Xor == node->opcode());
1261 19204 : Int32BinopMatcher m(node);
1262 : Node* shl = nullptr;
1263 : Node* shr = nullptr;
1264 : // Recognize rotation, we are matching:
1265 : // * x << y | x >>> (32 - y) => x ror (32 - y), i.e x rol y
1266 : // * x << (32 - y) | x >>> y => x ror y
1267 : // * x << y ^ x >>> (32 - y) => x ror (32 - y), i.e. x rol y
1268 : // * x << (32 - y) ^ x >>> y => x ror y
1269 : // as well as their commuted form.
1270 23753 : if (m.left().IsWord32Shl() && m.right().IsWord32Shr()) {
1271 : shl = m.left().node();
1272 : shr = m.right().node();
1273 18947 : } else if (m.left().IsWord32Shr() && m.right().IsWord32Shl()) {
1274 : shl = m.right().node();
1275 : shr = m.left().node();
1276 : } else {
1277 : return NoChange();
1278 : }
1279 :
1280 693 : Int32BinopMatcher mshl(shl);
1281 693 : Int32BinopMatcher mshr(shr);
1282 693 : if (mshl.left().node() != mshr.left().node()) return NoChange();
1283 :
1284 504 : if (mshl.right().HasValue() && mshr.right().HasValue()) {
1285 : // Case where y is a constant.
1286 370 : if (mshl.right().Value() + mshr.right().Value() != 32) return NoChange();
1287 : } else {
1288 : Node* sub = nullptr;
1289 : Node* y = nullptr;
1290 134 : if (mshl.right().IsInt32Sub()) {
1291 : sub = mshl.right().node();
1292 : y = mshr.right().node();
1293 124 : } else if (mshr.right().IsInt32Sub()) {
1294 : sub = mshr.right().node();
1295 : y = mshl.right().node();
1296 : } else {
1297 74 : return NoChange();
1298 : }
1299 :
1300 60 : Int32BinopMatcher msub(sub);
1301 120 : if (!msub.left().Is(32) || msub.right().node() != y) return NoChange();
1302 : }
1303 :
1304 430 : node->ReplaceInput(0, mshl.left().node());
1305 430 : node->ReplaceInput(1, mshr.right().node());
1306 430 : NodeProperties::ChangeOp(node, machine()->Word32Ror());
1307 : return Changed(node);
1308 : }
1309 :
1310 55869 : Reduction MachineOperatorReducer::ReduceWord32Or(Node* node) {
1311 : DCHECK_EQ(IrOpcode::kWord32Or, node->opcode());
1312 55869 : Int32BinopMatcher m(node);
1313 55870 : if (m.right().Is(0)) return Replace(m.left().node()); // x | 0 => x
1314 39881 : if (m.right().Is(-1)) return Replace(m.right().node()); // x | -1 => -1
1315 36469 : if (m.IsFoldable()) { // K | K => K
1316 20621 : return ReplaceInt32(m.left().Value() | m.right().Value());
1317 : }
1318 15848 : if (m.LeftEqualsRight()) return Replace(m.left().node()); // x | x => x
1319 :
1320 15785 : return TryMatchWord32Ror(node);
1321 : }
1322 :
1323 25034 : Reduction MachineOperatorReducer::ReduceWord32Xor(Node* node) {
1324 : DCHECK_EQ(IrOpcode::kWord32Xor, node->opcode());
1325 25034 : Int32BinopMatcher m(node);
1326 25034 : if (m.right().Is(0)) return Replace(m.left().node()); // x ^ 0 => x
1327 24436 : if (m.IsFoldable()) { // K ^ K => K
1328 20988 : return ReplaceInt32(m.left().Value() ^ m.right().Value());
1329 : }
1330 3448 : if (m.LeftEqualsRight()) return ReplaceInt32(0); // x ^ x => 0
1331 3642 : if (m.left().IsWord32Xor() && m.right().Is(-1)) {
1332 11 : Int32BinopMatcher mleft(m.left().node());
1333 11 : if (mleft.right().Is(-1)) { // (x ^ -1) ^ -1 => x
1334 11 : return Replace(mleft.left().node());
1335 : }
1336 : }
1337 :
1338 3419 : return TryMatchWord32Ror(node);
1339 : }
1340 :
1341 4800 : Reduction MachineOperatorReducer::ReduceFloat64InsertLowWord32(Node* node) {
1342 : DCHECK_EQ(IrOpcode::kFloat64InsertLowWord32, node->opcode());
1343 : Float64Matcher mlhs(node->InputAt(0));
1344 : Uint32Matcher mrhs(node->InputAt(1));
1345 4800 : if (mlhs.HasValue() && mrhs.HasValue()) {
1346 : return ReplaceFloat64(bit_cast<double>(
1347 4800 : (bit_cast<uint64_t>(mlhs.Value()) & V8_UINT64_C(0xFFFFFFFF00000000)) |
1348 : mrhs.Value()));
1349 : }
1350 : return NoChange();
1351 : }
1352 :
1353 :
1354 4800 : Reduction MachineOperatorReducer::ReduceFloat64InsertHighWord32(Node* node) {
1355 : DCHECK_EQ(IrOpcode::kFloat64InsertHighWord32, node->opcode());
1356 : Float64Matcher mlhs(node->InputAt(0));
1357 : Uint32Matcher mrhs(node->InputAt(1));
1358 4800 : if (mlhs.HasValue() && mrhs.HasValue()) {
1359 : return ReplaceFloat64(bit_cast<double>(
1360 9600 : (bit_cast<uint64_t>(mlhs.Value()) & V8_UINT64_C(0xFFFFFFFF)) |
1361 4800 : (static_cast<uint64_t>(mrhs.Value()) << 32)));
1362 : }
1363 : return NoChange();
1364 : }
1365 :
1366 :
1367 : namespace {
1368 :
1369 : bool IsFloat64RepresentableAsFloat32(const Float64Matcher& m) {
1370 167528 : if (m.HasValue()) {
1371 74084 : double v = m.Value();
1372 74084 : float fv = static_cast<float>(v);
1373 74084 : return static_cast<double>(fv) == v;
1374 : }
1375 : return false;
1376 : }
1377 :
1378 : } // namespace
1379 :
1380 :
1381 169242 : Reduction MachineOperatorReducer::ReduceFloat64Compare(Node* node) {
1382 : DCHECK((IrOpcode::kFloat64Equal == node->opcode()) ||
1383 : (IrOpcode::kFloat64LessThan == node->opcode()) ||
1384 : (IrOpcode::kFloat64LessThanOrEqual == node->opcode()));
1385 : // As all Float32 values have an exact representation in Float64, comparing
1386 : // two Float64 values both converted from Float32 is equivalent to comparing
1387 : // the original Float32s, so we can ignore the conversions. We can also reduce
1388 : // comparisons of converted Float64 values against constants that can be
1389 : // represented exactly as Float32.
1390 167910 : Float64BinopMatcher m(node);
1391 169291 : if ((m.left().IsChangeFloat32ToFloat64() &&
1392 167224 : m.right().IsChangeFloat32ToFloat64()) ||
1393 693 : (m.left().IsChangeFloat32ToFloat64() &&
1394 334746 : IsFloat64RepresentableAsFloat32(m.right())) ||
1395 71788 : (IsFloat64RepresentableAsFloat32(m.left()) &&
1396 : m.right().IsChangeFloat32ToFloat64())) {
1397 1332 : switch (node->opcode()) {
1398 : case IrOpcode::kFloat64Equal:
1399 312 : NodeProperties::ChangeOp(node, machine()->Float32Equal());
1400 312 : break;
1401 : case IrOpcode::kFloat64LessThan:
1402 720 : NodeProperties::ChangeOp(node, machine()->Float32LessThan());
1403 720 : break;
1404 : case IrOpcode::kFloat64LessThanOrEqual:
1405 300 : NodeProperties::ChangeOp(node, machine()->Float32LessThanOrEqual());
1406 300 : break;
1407 : default:
1408 : return NoChange();
1409 : }
1410 : node->ReplaceInput(
1411 1332 : 0, m.left().HasValue()
1412 256 : ? Float32Constant(static_cast<float>(m.left().Value()))
1413 2920 : : m.left().InputAt(0));
1414 : node->ReplaceInput(
1415 1332 : 1, m.right().HasValue()
1416 389 : ? Float32Constant(static_cast<float>(m.right().Value()))
1417 3053 : : m.right().InputAt(0));
1418 : return Changed(node);
1419 : }
1420 : return NoChange();
1421 : }
1422 :
1423 18166 : Reduction MachineOperatorReducer::ReduceFloat64RoundDown(Node* node) {
1424 : DCHECK_EQ(IrOpcode::kFloat64RoundDown, node->opcode());
1425 : Float64Matcher m(node->InputAt(0));
1426 18166 : if (m.HasValue()) {
1427 : return ReplaceFloat64(Floor(m.Value()));
1428 : }
1429 : return NoChange();
1430 : }
1431 :
1432 631820 : CommonOperatorBuilder* MachineOperatorReducer::common() const {
1433 631820 : return jsgraph()->common();
1434 : }
1435 :
1436 :
1437 501266 : MachineOperatorBuilder* MachineOperatorReducer::machine() const {
1438 501266 : return jsgraph()->machine();
1439 : }
1440 :
1441 :
1442 779989 : Graph* MachineOperatorReducer::graph() const { return jsgraph()->graph(); }
1443 :
1444 : } // namespace compiler
1445 : } // namespace internal
1446 : } // namespace v8
|