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 : #include <cmath>
7 :
8 : #include "src/base/bits.h"
9 : #include "src/base/division-by-constant.h"
10 : #include "src/base/ieee754.h"
11 : #include "src/base/overflowing-math.h"
12 : #include "src/compiler/diamond.h"
13 : #include "src/compiler/graph.h"
14 : #include "src/compiler/machine-graph.h"
15 : #include "src/compiler/node-matchers.h"
16 : #include "src/compiler/node-properties.h"
17 : #include "src/conversions-inl.h"
18 :
19 : namespace v8 {
20 : namespace internal {
21 : namespace compiler {
22 :
23 2149342 : MachineOperatorReducer::MachineOperatorReducer(Editor* editor,
24 : MachineGraph* mcgraph,
25 : bool allow_signalling_nan)
26 : : AdvancedReducer(editor),
27 : mcgraph_(mcgraph),
28 2149342 : allow_signalling_nan_(allow_signalling_nan) {}
29 :
30 : MachineOperatorReducer::~MachineOperatorReducer() = default;
31 :
32 :
33 66858 : Node* MachineOperatorReducer::Float32Constant(volatile float value) {
34 133716 : return graph()->NewNode(common()->Float32Constant(value));
35 : }
36 :
37 :
38 0 : Node* MachineOperatorReducer::Float64Constant(volatile double value) {
39 87682 : return mcgraph()->Float64Constant(value);
40 : }
41 :
42 :
43 0 : Node* MachineOperatorReducer::Int32Constant(int32_t value) {
44 531756 : return mcgraph()->Int32Constant(value);
45 : }
46 :
47 :
48 547052 : Node* MachineOperatorReducer::Int64Constant(int64_t value) {
49 1094105 : return graph()->NewNode(common()->Int64Constant(value));
50 : }
51 :
52 0 : Node* MachineOperatorReducer::Float64Mul(Node* lhs, Node* rhs) {
53 0 : return graph()->NewNode(machine()->Float64Mul(), lhs, rhs);
54 : }
55 :
56 0 : Node* MachineOperatorReducer::Float64PowHalf(Node* value) {
57 : value =
58 0 : graph()->NewNode(machine()->Float64Add(), Float64Constant(0.0), value);
59 : Diamond d(graph(), common(),
60 : graph()->NewNode(machine()->Float64LessThanOrEqual(), value,
61 : Float64Constant(-V8_INFINITY)),
62 0 : BranchHint::kFalse);
63 0 : return d.Phi(MachineRepresentation::kFloat64, Float64Constant(V8_INFINITY),
64 0 : graph()->NewNode(machine()->Float64Sqrt(), value));
65 : }
66 :
67 88614 : Node* MachineOperatorReducer::Word32And(Node* lhs, Node* rhs) {
68 88614 : Node* const node = graph()->NewNode(machine()->Word32And(), lhs, rhs);
69 88614 : Reduction const reduction = ReduceWord32And(node);
70 88614 : return reduction.Changed() ? reduction.replacement() : node;
71 : }
72 :
73 :
74 5520 : Node* MachineOperatorReducer::Word32Sar(Node* lhs, uint32_t rhs) {
75 5520 : if (rhs == 0) return lhs;
76 10718 : return graph()->NewNode(machine()->Word32Sar(), lhs, Uint32Constant(rhs));
77 : }
78 :
79 :
80 7276 : Node* MachineOperatorReducer::Word32Shr(Node* lhs, uint32_t rhs) {
81 7276 : if (rhs == 0) return lhs;
82 12742 : return graph()->NewNode(machine()->Word32Shr(), lhs, Uint32Constant(rhs));
83 : }
84 :
85 :
86 4 : Node* MachineOperatorReducer::Word32Equal(Node* lhs, Node* rhs) {
87 8 : return graph()->NewNode(machine()->Word32Equal(), lhs, rhs);
88 : }
89 :
90 :
91 6187 : Node* MachineOperatorReducer::Int32Add(Node* lhs, Node* rhs) {
92 6187 : Node* const node = graph()->NewNode(machine()->Int32Add(), lhs, rhs);
93 6187 : Reduction const reduction = ReduceInt32Add(node);
94 6187 : return reduction.Changed() ? reduction.replacement() : node;
95 : }
96 :
97 :
98 1534 : Node* MachineOperatorReducer::Int32Sub(Node* lhs, Node* rhs) {
99 1534 : Node* const node = graph()->NewNode(machine()->Int32Sub(), lhs, rhs);
100 1534 : Reduction const reduction = ReduceInt32Sub(node);
101 1534 : return reduction.Changed() ? reduction.replacement() : node;
102 : }
103 :
104 :
105 3208 : Node* MachineOperatorReducer::Int32Mul(Node* lhs, Node* rhs) {
106 6416 : return graph()->NewNode(machine()->Int32Mul(), lhs, rhs);
107 : }
108 :
109 :
110 4150 : Node* MachineOperatorReducer::Int32Div(Node* dividend, int32_t divisor) {
111 : DCHECK_NE(0, divisor);
112 : DCHECK_NE(std::numeric_limits<int32_t>::min(), divisor);
113 : base::MagicNumbersForDivision<uint32_t> const mag =
114 4150 : base::SignedDivisionByConstant(bit_cast<uint32_t>(divisor));
115 4150 : Node* quotient = graph()->NewNode(machine()->Int32MulHigh(), dividend,
116 : Uint32Constant(mag.multiplier));
117 4150 : if (divisor > 0 && bit_cast<int32_t>(mag.multiplier) < 0) {
118 1275 : quotient = Int32Add(quotient, dividend);
119 2875 : } else if (divisor < 0 && bit_cast<int32_t>(mag.multiplier) > 0) {
120 0 : quotient = Int32Sub(quotient, dividend);
121 : }
122 4150 : return Int32Add(Word32Sar(quotient, mag.shift), Word32Shr(dividend, 31));
123 : }
124 :
125 :
126 1182 : Node* MachineOperatorReducer::Uint32Div(Node* dividend, uint32_t divisor) {
127 : DCHECK_LT(0u, divisor);
128 : // If the divisor is even, we can avoid using the expensive fixup by shifting
129 : // the dividend upfront.
130 : unsigned const shift = base::bits::CountTrailingZeros(divisor);
131 1182 : dividend = Word32Shr(dividend, shift);
132 1182 : divisor >>= shift;
133 : // Compute the magic number for the (shifted) divisor.
134 : base::MagicNumbersForDivision<uint32_t> const mag =
135 1182 : base::UnsignedDivisionByConstant(divisor, shift);
136 1182 : Node* quotient = graph()->NewNode(machine()->Uint32MulHigh(), dividend,
137 1182 : Uint32Constant(mag.multiplier));
138 1182 : if (mag.add) {
139 : DCHECK_LE(1u, mag.shift);
140 24 : quotient = Word32Shr(
141 : Int32Add(Word32Shr(Int32Sub(dividend, quotient), 1), quotient),
142 24 : mag.shift - 1);
143 : } else {
144 1158 : quotient = Word32Shr(quotient, mag.shift);
145 : }
146 1182 : return quotient;
147 : }
148 :
149 :
150 : // Perform constant folding and strength reduction on machine operators.
151 163018995 : Reduction MachineOperatorReducer::Reduce(Node* node) {
152 163018995 : switch (node->opcode()) {
153 : case IrOpcode::kProjection:
154 390538 : return ReduceProjection(ProjectionIndexOf(node->op()), node->InputAt(0));
155 : case IrOpcode::kWord32And:
156 654598 : return ReduceWord32And(node);
157 : case IrOpcode::kWord32Or:
158 80866 : return ReduceWord32Or(node);
159 : case IrOpcode::kWord32Xor:
160 23381 : return ReduceWord32Xor(node);
161 : case IrOpcode::kWord32Shl:
162 41528 : return ReduceWord32Shl(node);
163 : case IrOpcode::kWord64Shl:
164 697362 : return ReduceWord64Shl(node);
165 : case IrOpcode::kWord32Shr:
166 80421 : return ReduceWord32Shr(node);
167 : case IrOpcode::kWord64Shr:
168 50050 : return ReduceWord64Shr(node);
169 : case IrOpcode::kWord32Sar:
170 39186 : return ReduceWord32Sar(node);
171 : case IrOpcode::kWord64Sar:
172 477253 : return ReduceWord64Sar(node);
173 : case IrOpcode::kWord32Ror: {
174 2261 : Int32BinopMatcher m(node);
175 3805 : if (m.right().Is(0)) return Replace(m.left().node()); // x ror 0 => x
176 2212 : if (m.IsFoldable()) { // K ror K => K
177 1495 : return ReplaceInt32(base::bits::RotateRight32(m.left().Value(),
178 2990 : m.right().Value() & 31));
179 : }
180 717 : break;
181 : }
182 : case IrOpcode::kWord32Equal: {
183 1261814 : Int32BinopMatcher m(node);
184 1261814 : if (m.IsFoldable()) { // K == K => K
185 64054 : return ReplaceBool(m.left().Value() == m.right().Value());
186 : }
187 1231399 : if (m.left().IsInt32Sub() && m.right().Is(0)) { // x - y == 0 => x == y
188 712 : Int32BinopMatcher msub(m.left().node());
189 712 : node->ReplaceInput(0, msub.left().node());
190 712 : node->ReplaceInput(1, msub.right().node());
191 : return Changed(node);
192 : }
193 : // TODO(turbofan): fold HeapConstant, ExternalReference, pointer compares
194 1229442 : if (m.LeftEqualsRight()) return ReplaceBool(true); // x == x => true
195 1229420 : break;
196 : }
197 : case IrOpcode::kWord64Equal: {
198 2943308 : Int64BinopMatcher m(node);
199 2943309 : if (m.IsFoldable()) { // K == K => K
200 15565 : return ReplaceBool(m.left().Value() == m.right().Value());
201 : }
202 2947956 : if (m.left().IsInt64Sub() && m.right().Is(0)) { // x - y == 0 => x == y
203 728 : Int64BinopMatcher msub(m.left().node());
204 728 : node->ReplaceInput(0, msub.left().node());
205 728 : node->ReplaceInput(1, msub.right().node());
206 : return Changed(node);
207 : }
208 : // TODO(turbofan): fold HeapConstant, ExternalReference, pointer compares
209 2939744 : if (m.LeftEqualsRight()) return ReplaceBool(true); // x == x => true
210 2930581 : break;
211 : }
212 : case IrOpcode::kInt32Add:
213 453998 : return ReduceInt32Add(node);
214 : case IrOpcode::kInt64Add:
215 1541871 : return ReduceInt64Add(node);
216 : case IrOpcode::kInt32Sub:
217 61337 : return ReduceInt32Sub(node);
218 : case IrOpcode::kInt64Sub:
219 312715 : return ReduceInt64Sub(node);
220 : case IrOpcode::kInt32Mul: {
221 46235 : Int32BinopMatcher m(node);
222 66938 : if (m.right().Is(0)) return Replace(m.right().node()); // x * 0 => 0
223 45870 : if (m.right().Is(1)) return Replace(m.left().node()); // x * 1 => x
224 45569 : if (m.IsFoldable()) { // K * K => K
225 : return ReplaceInt32(
226 18134 : base::MulWithWraparound(m.left().Value(), m.right().Value()));
227 : }
228 27435 : if (m.right().Is(-1)) { // x * -1 => 0 - x
229 67 : node->ReplaceInput(0, Int32Constant(0));
230 67 : node->ReplaceInput(1, m.left().node());
231 67 : NodeProperties::ChangeOp(node, machine()->Int32Sub());
232 : return Changed(node);
233 : }
234 27368 : if (m.right().IsPowerOf2()) { // x * 2^n => x << n
235 3672 : node->ReplaceInput(1, Int32Constant(WhichPowerOf2(m.right().Value())));
236 1836 : NodeProperties::ChangeOp(node, machine()->Word32Shl());
237 1836 : Reduction reduction = ReduceWord32Shl(node);
238 1836 : return reduction.Changed() ? reduction : Changed(node);
239 : }
240 25532 : break;
241 : }
242 : case IrOpcode::kInt32MulWithOverflow: {
243 9122 : Int32BinopMatcher m(node);
244 9122 : if (m.right().Is(2)) {
245 340 : node->ReplaceInput(1, m.left().node());
246 340 : NodeProperties::ChangeOp(node, machine()->Int32AddWithOverflow());
247 3486 : return Changed(node);
248 : }
249 8782 : if (m.right().Is(-1)) {
250 3146 : node->ReplaceInput(0, Int32Constant(0));
251 3146 : node->ReplaceInput(1, m.left().node());
252 3146 : NodeProperties::ChangeOp(node, machine()->Int32SubWithOverflow());
253 : return Changed(node);
254 : }
255 5636 : break;
256 : }
257 : case IrOpcode::kInt32Div:
258 20528 : return ReduceInt32Div(node);
259 : case IrOpcode::kUint32Div:
260 19320 : return ReduceUint32Div(node);
261 : case IrOpcode::kInt32Mod:
262 30533 : return ReduceInt32Mod(node);
263 : case IrOpcode::kUint32Mod:
264 21180 : return ReduceUint32Mod(node);
265 : case IrOpcode::kInt32LessThan: {
266 372170 : Int32BinopMatcher m(node);
267 372193 : if (m.IsFoldable()) { // K < K => K
268 40109 : return ReplaceBool(m.left().Value() < m.right().Value());
269 : }
270 352180 : if (m.LeftEqualsRight()) return ReplaceBool(false); // x < x => false
271 354373 : if (m.left().IsWord32Or() && m.right().Is(0)) {
272 : // (x | K) < 0 => true or (K | x) < 0 => true iff K < 0
273 2170 : Int32BinopMatcher mleftmatcher(m.left().node());
274 4340 : if (mleftmatcher.left().IsNegative() ||
275 : mleftmatcher.right().IsNegative()) {
276 71 : return ReplaceBool(true);
277 : }
278 : }
279 352097 : break;
280 : }
281 : case IrOpcode::kInt32LessThanOrEqual: {
282 49668 : Int32BinopMatcher m(node);
283 49668 : if (m.IsFoldable()) { // K <= K => K
284 35281 : return ReplaceBool(m.left().Value() <= m.right().Value());
285 : }
286 32030 : if (m.LeftEqualsRight()) return ReplaceBool(true); // x <= x => true
287 32025 : break;
288 : }
289 : case IrOpcode::kUint32LessThan: {
290 264724 : Uint32BinopMatcher m(node);
291 286497 : if (m.left().Is(kMaxUInt32)) return ReplaceBool(false); // M < x => false
292 264413 : if (m.right().Is(0)) return ReplaceBool(false); // x < 0 => false
293 263994 : if (m.IsFoldable()) { // K < K => K
294 20592 : return ReplaceBool(m.left().Value() < m.right().Value());
295 : }
296 243402 : if (m.LeftEqualsRight()) return ReplaceBool(false); // x < x => false
297 243250 : if (m.left().IsWord32Sar() && m.right().HasValue()) {
298 371 : Int32BinopMatcher mleft(m.left().node());
299 371 : if (mleft.right().HasValue()) {
300 : // (x >> K) < C => x < (C << K)
301 : // when C < (M >> K)
302 371 : const uint32_t c = m.right().Value();
303 371 : const uint32_t k = mleft.right().Value() & 0x1F;
304 371 : if (c < static_cast<uint32_t>(kMaxInt >> k)) {
305 299 : node->ReplaceInput(0, mleft.left().node());
306 598 : node->ReplaceInput(1, Uint32Constant(c << k));
307 299 : return Changed(node);
308 : }
309 : // TODO(turbofan): else the comparison is always true.
310 : }
311 : }
312 242951 : break;
313 : }
314 : case IrOpcode::kUint32LessThanOrEqual: {
315 91412 : Uint32BinopMatcher m(node);
316 108574 : if (m.left().Is(0)) return ReplaceBool(true); // 0 <= x => true
317 90998 : if (m.right().Is(kMaxUInt32)) return ReplaceBool(true); // x <= M => true
318 90708 : if (m.IsFoldable()) { // K <= K => K
319 16452 : return ReplaceBool(m.left().Value() <= m.right().Value());
320 : }
321 74256 : if (m.LeftEqualsRight()) return ReplaceBool(true); // x <= x => true
322 74250 : break;
323 : }
324 : case IrOpcode::kFloat32Sub: {
325 66141 : Float32BinopMatcher m(node);
326 133432 : if (allow_signalling_nan_ && m.right().Is(0) &&
327 1150 : (std::copysign(1.0, m.right().Value()) > 0)) {
328 66136 : return Replace(m.left().node()); // x - 0 => x
329 : }
330 65566 : if (m.right().IsNaN()) { // x - NaN => NaN
331 : // Do some calculation to make a signalling NaN quiet.
332 1155 : return ReplaceFloat32(m.right().Value() - m.right().Value());
333 : }
334 64411 : if (m.left().IsNaN()) { // NaN - x => NaN
335 : // Do some calculation to make a signalling NaN quiet.
336 1125 : return ReplaceFloat32(m.left().Value() - m.left().Value());
337 : }
338 63286 : if (m.IsFoldable()) { // L - R => (L - R)
339 63280 : return ReplaceFloat32(m.left().Value() - m.right().Value());
340 : }
341 6 : if (allow_signalling_nan_ && m.left().IsMinusZero()) {
342 : // -0.0 - round_down(-0.0 - R) => round_up(R)
343 1 : if (machine()->Float32RoundUp().IsSupported() &&
344 : m.right().IsFloat32RoundDown()) {
345 0 : if (m.right().InputAt(0)->opcode() == IrOpcode::kFloat32Sub) {
346 0 : Float32BinopMatcher mright0(m.right().InputAt(0));
347 0 : if (mright0.left().IsMinusZero()) {
348 0 : return Replace(graph()->NewNode(machine()->Float32RoundUp().op(),
349 : mright0.right().node()));
350 : }
351 : }
352 : }
353 : // -0.0 - R => -R
354 1 : node->RemoveInput(0);
355 1 : NodeProperties::ChangeOp(node, machine()->Float32Neg());
356 : return Changed(node);
357 : }
358 5 : break;
359 : }
360 : case IrOpcode::kFloat64Add: {
361 207059 : Float64BinopMatcher m(node);
362 207072 : if (m.IsFoldable()) { // K + K => K
363 22136 : return ReplaceFloat64(m.left().Value() + m.right().Value());
364 : }
365 196004 : break;
366 : }
367 : case IrOpcode::kFloat64Sub: {
368 39638 : Float64BinopMatcher m(node);
369 79791 : if (allow_signalling_nan_ && m.right().Is(0) &&
370 515 : (Double(m.right().Value()).Sign() > 0)) {
371 20670 : return Replace(m.left().node()); // x - 0 => x
372 : }
373 39368 : if (m.right().IsNaN()) { // x - NaN => NaN
374 : // Do some calculation to make a signalling NaN quiet.
375 509 : return ReplaceFloat64(m.right().Value() - m.right().Value());
376 : }
377 38859 : if (m.left().IsNaN()) { // NaN - x => NaN
378 : // Do some calculation to make a signalling NaN quiet.
379 479 : return ReplaceFloat64(m.left().Value() - m.left().Value());
380 : }
381 38380 : if (m.IsFoldable()) { // L - R => (L - R)
382 10989 : return ReplaceFloat64(m.left().Value() - m.right().Value());
383 : }
384 27391 : if (allow_signalling_nan_ && m.left().IsMinusZero()) {
385 : // -0.0 - round_down(-0.0 - R) => round_up(R)
386 16844 : if (machine()->Float64RoundUp().IsSupported() &&
387 : m.right().IsFloat64RoundDown()) {
388 630 : if (m.right().InputAt(0)->opcode() == IrOpcode::kFloat64Sub) {
389 0 : Float64BinopMatcher mright0(m.right().InputAt(0));
390 0 : if (mright0.left().IsMinusZero()) {
391 0 : return Replace(graph()->NewNode(machine()->Float64RoundUp().op(),
392 : mright0.right().node()));
393 : }
394 : }
395 : }
396 : // -0.0 - R => -R
397 8423 : node->RemoveInput(0);
398 8423 : NodeProperties::ChangeOp(node, machine()->Float64Neg());
399 : return Changed(node);
400 : }
401 18968 : break;
402 : }
403 : case IrOpcode::kFloat64Mul: {
404 25339 : Float64BinopMatcher m(node);
405 50678 : if (allow_signalling_nan_ && m.right().Is(1))
406 9315 : return Replace(m.left().node()); // x * 1.0 => x
407 25289 : if (m.right().Is(-1)) { // x * -1.0 => -0.0 - x
408 8585 : node->ReplaceInput(0, Float64Constant(-0.0));
409 8585 : node->ReplaceInput(1, m.left().node());
410 8585 : NodeProperties::ChangeOp(node, machine()->Float64Sub());
411 : return Changed(node);
412 : }
413 16704 : if (m.right().IsNaN()) { // x * NaN => NaN
414 : // Do some calculation to make a signalling NaN quiet.
415 7 : return ReplaceFloat64(m.right().Value() - m.right().Value());
416 : }
417 16697 : if (m.IsFoldable()) { // K * K => K
418 538 : return ReplaceFloat64(m.left().Value() * m.right().Value());
419 : }
420 16159 : if (m.right().Is(2)) { // x * 2.0 => x + x
421 135 : node->ReplaceInput(1, m.left().node());
422 135 : NodeProperties::ChangeOp(node, machine()->Float64Add());
423 : return Changed(node);
424 : }
425 16024 : break;
426 : }
427 : case IrOpcode::kFloat64Div: {
428 38361 : Float64BinopMatcher m(node);
429 76722 : if (allow_signalling_nan_ && m.right().Is(1))
430 4909 : return Replace(m.left().node()); // x / 1.0 => x
431 : // TODO(ahaas): We could do x / 1.0 = x if we knew that x is not an sNaN.
432 38228 : if (m.right().IsNaN()) { // x / NaN => NaN
433 : // Do some calculation to make a signalling NaN quiet.
434 0 : return ReplaceFloat64(m.right().Value() - m.right().Value());
435 : }
436 38228 : if (m.left().IsNaN()) { // NaN / x => NaN
437 : // Do some calculation to make a signalling NaN quiet.
438 0 : return ReplaceFloat64(m.left().Value() - m.left().Value());
439 : }
440 38228 : if (m.IsFoldable()) { // K / K => K
441 : return ReplaceFloat64(
442 1900 : base::Divide(m.left().Value(), m.right().Value()));
443 : }
444 72656 : if (allow_signalling_nan_ && m.right().Is(-1)) { // x / -1.0 => -x
445 36 : node->RemoveInput(1);
446 36 : NodeProperties::ChangeOp(node, machine()->Float64Neg());
447 : return Changed(node);
448 : }
449 36292 : if (m.right().IsNormal() && m.right().IsPositiveOrNegativePowerOf2()) {
450 : // All reciprocals of non-denormal powers of two can be represented
451 : // exactly, so division by power of two can be reduced to
452 : // multiplication by reciprocal, with the same result.
453 5680 : node->ReplaceInput(1, Float64Constant(1.0 / m.right().Value()));
454 2840 : NodeProperties::ChangeOp(node, machine()->Float64Mul());
455 : return Changed(node);
456 : }
457 33452 : break;
458 : }
459 : case IrOpcode::kFloat64Mod: {
460 2306 : Float64BinopMatcher m(node);
461 2306 : if (m.right().Is(0)) { // x % 0 => NaN
462 25 : return ReplaceFloat64(std::numeric_limits<double>::quiet_NaN());
463 : }
464 2306 : if (m.right().IsNaN()) { // x % NaN => NaN
465 : return Replace(m.right().node());
466 : }
467 2306 : if (m.left().IsNaN()) { // NaN % x => NaN
468 : return Replace(m.left().node());
469 : }
470 2306 : if (m.IsFoldable()) { // K % K => K
471 25 : return ReplaceFloat64(Modulo(m.left().Value(), m.right().Value()));
472 : }
473 2281 : break;
474 : }
475 : case IrOpcode::kFloat64Acos: {
476 : Float64Matcher m(node->InputAt(0));
477 156 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::acos(m.Value()));
478 : break;
479 : }
480 : case IrOpcode::kFloat64Acosh: {
481 : Float64Matcher m(node->InputAt(0));
482 156 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::acosh(m.Value()));
483 : break;
484 : }
485 : case IrOpcode::kFloat64Asin: {
486 : Float64Matcher m(node->InputAt(0));
487 163 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::asin(m.Value()));
488 : break;
489 : }
490 : case IrOpcode::kFloat64Asinh: {
491 : Float64Matcher m(node->InputAt(0));
492 156 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::asinh(m.Value()));
493 : break;
494 : }
495 : case IrOpcode::kFloat64Atan: {
496 : Float64Matcher m(node->InputAt(0));
497 169 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::atan(m.Value()));
498 : break;
499 : }
500 : case IrOpcode::kFloat64Atanh: {
501 : Float64Matcher m(node->InputAt(0));
502 156 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::atanh(m.Value()));
503 : break;
504 : }
505 : case IrOpcode::kFloat64Atan2: {
506 10068 : Float64BinopMatcher m(node);
507 10068 : if (m.right().IsNaN()) {
508 10006 : return Replace(m.right().node());
509 : }
510 10067 : if (m.left().IsNaN()) {
511 : return Replace(m.left().node());
512 : }
513 10066 : if (m.IsFoldable()) {
514 : return ReplaceFloat64(
515 10004 : base::ieee754::atan2(m.left().Value(), m.right().Value()));
516 : }
517 62 : break;
518 : }
519 : case IrOpcode::kFloat64Cbrt: {
520 : Float64Matcher m(node->InputAt(0));
521 56 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::cbrt(m.Value()));
522 : break;
523 : }
524 : case IrOpcode::kFloat64Cos: {
525 : Float64Matcher m(node->InputAt(0));
526 334 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::cos(m.Value()));
527 : break;
528 : }
529 : case IrOpcode::kFloat64Cosh: {
530 : Float64Matcher m(node->InputAt(0));
531 177 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::cosh(m.Value()));
532 : break;
533 : }
534 : case IrOpcode::kFloat64Exp: {
535 : Float64Matcher m(node->InputAt(0));
536 237 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::exp(m.Value()));
537 : break;
538 : }
539 : case IrOpcode::kFloat64Expm1: {
540 : Float64Matcher m(node->InputAt(0));
541 84 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::expm1(m.Value()));
542 : break;
543 : }
544 : case IrOpcode::kFloat64Log: {
545 : Float64Matcher m(node->InputAt(0));
546 538 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::log(m.Value()));
547 : break;
548 : }
549 : case IrOpcode::kFloat64Log1p: {
550 : Float64Matcher m(node->InputAt(0));
551 156 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::log1p(m.Value()));
552 : break;
553 : }
554 : case IrOpcode::kFloat64Log10: {
555 : Float64Matcher m(node->InputAt(0));
556 56 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::log10(m.Value()));
557 : break;
558 : }
559 : case IrOpcode::kFloat64Log2: {
560 : Float64Matcher m(node->InputAt(0));
561 56 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::log2(m.Value()));
562 : break;
563 : }
564 : case IrOpcode::kFloat64Pow: {
565 11235 : Float64BinopMatcher m(node);
566 11235 : if (m.IsFoldable()) {
567 : return ReplaceFloat64(
568 21546 : base::ieee754::pow(m.left().Value(), m.right().Value()));
569 463 : } else if (m.right().Is(0.0)) { // x ** +-0.0 => 1.0
570 : return ReplaceFloat64(1.0);
571 461 : } else if (m.right().Is(-2.0)) { // x ** -2.0 => 1 / (x * x)
572 0 : node->ReplaceInput(0, Float64Constant(1.0));
573 0 : node->ReplaceInput(1, Float64Mul(m.left().node(), m.left().node()));
574 0 : NodeProperties::ChangeOp(node, machine()->Float64Div());
575 : return Changed(node);
576 461 : } else if (m.right().Is(2.0)) { // x ** 2.0 => x * x
577 0 : node->ReplaceInput(1, m.left().node());
578 0 : NodeProperties::ChangeOp(node, machine()->Float64Mul());
579 : return Changed(node);
580 461 : } else if (m.right().Is(-0.5)) {
581 : // x ** 0.5 => 1 / (if x <= -Infinity then Infinity else sqrt(0.0 + x))
582 0 : node->ReplaceInput(0, Float64Constant(1.0));
583 0 : node->ReplaceInput(1, Float64PowHalf(m.left().node()));
584 0 : NodeProperties::ChangeOp(node, machine()->Float64Div());
585 : return Changed(node);
586 461 : } else if (m.right().Is(0.5)) {
587 : // x ** 0.5 => if x <= -Infinity then Infinity else sqrt(0.0 + x)
588 0 : return Replace(Float64PowHalf(m.left().node()));
589 : }
590 461 : break;
591 : }
592 : case IrOpcode::kFloat64Sin: {
593 : Float64Matcher m(node->InputAt(0));
594 345 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::sin(m.Value()));
595 : break;
596 : }
597 : case IrOpcode::kFloat64Sinh: {
598 : Float64Matcher m(node->InputAt(0));
599 177 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::sinh(m.Value()));
600 : break;
601 : }
602 : case IrOpcode::kFloat64Tan: {
603 : Float64Matcher m(node->InputAt(0));
604 239 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::tan(m.Value()));
605 : break;
606 : }
607 : case IrOpcode::kFloat64Tanh: {
608 : Float64Matcher m(node->InputAt(0));
609 177 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::tanh(m.Value()));
610 : break;
611 : }
612 : case IrOpcode::kChangeFloat32ToFloat64: {
613 : Float32Matcher m(node->InputAt(0));
614 13863 : if (m.HasValue()) {
615 160 : if (!allow_signalling_nan_ && std::isnan(m.Value())) {
616 : // Do some calculation to make guarantee the value is a quiet NaN.
617 0 : return ReplaceFloat64(m.Value() + m.Value());
618 : }
619 160 : return ReplaceFloat64(m.Value());
620 : }
621 : break;
622 : }
623 : case IrOpcode::kChangeFloat64ToInt32: {
624 : Float64Matcher m(node->InputAt(0));
625 5152 : if (m.HasValue()) return ReplaceInt32(FastD2IChecked(m.Value()));
626 5024 : if (m.IsChangeInt32ToFloat64()) return Replace(m.node()->InputAt(0));
627 : break;
628 : }
629 : case IrOpcode::kChangeFloat64ToInt64: {
630 : Float64Matcher m(node->InputAt(0));
631 162 : if (m.HasValue()) return ReplaceInt64(static_cast<int64_t>(m.Value()));
632 59 : if (m.IsChangeInt64ToFloat64()) return Replace(m.node()->InputAt(0));
633 : break;
634 : }
635 : case IrOpcode::kChangeFloat64ToUint32: {
636 : Float64Matcher m(node->InputAt(0));
637 1063 : if (m.HasValue()) return ReplaceInt32(FastD2UI(m.Value()));
638 967 : if (m.IsChangeUint32ToFloat64()) return Replace(m.node()->InputAt(0));
639 : break;
640 : }
641 : case IrOpcode::kChangeInt32ToFloat64: {
642 : Int32Matcher m(node->InputAt(0));
643 389541 : if (m.HasValue()) return ReplaceFloat64(FastI2D(m.Value()));
644 : break;
645 : }
646 : case IrOpcode::kChangeInt32ToInt64: {
647 : Int32Matcher m(node->InputAt(0));
648 381641 : if (m.HasValue()) return ReplaceInt64(m.Value());
649 : break;
650 : }
651 : case IrOpcode::kChangeInt64ToFloat64: {
652 : Int64Matcher m(node->InputAt(0));
653 653 : if (m.HasValue()) return ReplaceFloat64(static_cast<double>(m.Value()));
654 549 : if (m.IsChangeFloat64ToInt64()) return Replace(m.node()->InputAt(0));
655 : break;
656 : }
657 : case IrOpcode::kChangeUint32ToFloat64: {
658 : Uint32Matcher m(node->InputAt(0));
659 6263 : if (m.HasValue()) return ReplaceFloat64(FastUI2D(m.Value()));
660 : break;
661 : }
662 : case IrOpcode::kChangeUint32ToUint64: {
663 : Uint32Matcher m(node->InputAt(0));
664 301281 : if (m.HasValue()) return ReplaceInt64(static_cast<uint64_t>(m.Value()));
665 : break;
666 : }
667 : case IrOpcode::kTruncateFloat64ToWord32: {
668 : Float64Matcher m(node->InputAt(0));
669 28192 : if (m.HasValue()) return ReplaceInt32(DoubleToInt32(m.Value()));
670 27945 : if (m.IsChangeInt32ToFloat64()) return Replace(m.node()->InputAt(0));
671 : return NoChange();
672 : }
673 : case IrOpcode::kTruncateInt64ToInt32: {
674 : Int64Matcher m(node->InputAt(0));
675 435539 : if (m.HasValue()) return ReplaceInt32(static_cast<int32_t>(m.Value()));
676 425736 : if (m.IsChangeInt32ToInt64()) return Replace(m.node()->InputAt(0));
677 : break;
678 : }
679 : case IrOpcode::kTruncateFloat64ToFloat32: {
680 : Float64Matcher m(node->InputAt(0));
681 9145 : if (m.HasValue()) {
682 680 : if (!allow_signalling_nan_ && std::isnan(m.Value())) {
683 : // Do some calculation to make guarantee the value is a quiet NaN.
684 0 : return ReplaceFloat32(DoubleToFloat32(m.Value() + m.Value()));
685 : }
686 : return ReplaceFloat32(DoubleToFloat32(m.Value()));
687 : }
688 8465 : if (allow_signalling_nan_ && m.IsChangeFloat32ToFloat64())
689 : return Replace(m.node()->InputAt(0));
690 : break;
691 : }
692 : case IrOpcode::kRoundFloat64ToInt32: {
693 : Float64Matcher m(node->InputAt(0));
694 129655 : if (m.HasValue()) {
695 132 : return ReplaceInt32(DoubleToInt32(m.Value()));
696 : }
697 129523 : if (m.IsChangeInt32ToFloat64()) return Replace(m.node()->InputAt(0));
698 : break;
699 : }
700 : case IrOpcode::kFloat64InsertLowWord32:
701 4856 : return ReduceFloat64InsertLowWord32(node);
702 : case IrOpcode::kFloat64InsertHighWord32:
703 4856 : return ReduceFloat64InsertHighWord32(node);
704 : case IrOpcode::kStore:
705 : case IrOpcode::kUnalignedStore:
706 3239043 : return ReduceStore(node);
707 : case IrOpcode::kFloat64Equal:
708 : case IrOpcode::kFloat64LessThan:
709 : case IrOpcode::kFloat64LessThanOrEqual:
710 360814 : return ReduceFloat64Compare(node);
711 : case IrOpcode::kFloat64RoundDown:
712 81772 : return ReduceFloat64RoundDown(node);
713 : case IrOpcode::kBitcastTaggedToWord: {
714 : NodeMatcher m(node->InputAt(0));
715 1163724 : if (m.IsBitcastWordToTaggedSigned()) {
716 : RelaxEffectsAndControls(node);
717 : return Replace(m.InputAt(0));
718 : }
719 : break;
720 : }
721 : default:
722 : break;
723 : }
724 : return NoChange();
725 : }
726 :
727 560970 : Reduction MachineOperatorReducer::ReduceInt32Add(Node* node) {
728 : DCHECK_EQ(IrOpcode::kInt32Add, node->opcode());
729 560970 : Int32BinopMatcher m(node);
730 560982 : if (m.right().Is(0)) return Replace(m.left().node()); // x + 0 => x
731 537117 : if (m.IsFoldable()) { // K + K => K
732 : return ReplaceInt32(
733 38270 : base::AddWithWraparound(m.left().Value(), m.right().Value()));
734 : }
735 498847 : if (m.left().IsInt32Sub()) {
736 1474 : Int32BinopMatcher mleft(m.left().node());
737 1474 : if (mleft.left().Is(0)) { // (0 - x) + y => y - x
738 122 : node->ReplaceInput(0, m.right().node());
739 122 : node->ReplaceInput(1, mleft.right().node());
740 122 : NodeProperties::ChangeOp(node, machine()->Int32Sub());
741 122 : Reduction const reduction = ReduceInt32Sub(node);
742 122 : return reduction.Changed() ? reduction : Changed(node);
743 : }
744 : }
745 498725 : if (m.right().IsInt32Sub()) {
746 453 : Int32BinopMatcher mright(m.right().node());
747 453 : if (mright.left().Is(0)) { // y + (0 - x) => y - x
748 42 : node->ReplaceInput(1, mright.right().node());
749 42 : NodeProperties::ChangeOp(node, machine()->Int32Sub());
750 42 : Reduction const reduction = ReduceInt32Sub(node);
751 42 : return reduction.Changed() ? reduction : Changed(node);
752 : }
753 : }
754 : return NoChange();
755 : }
756 :
757 1796593 : Reduction MachineOperatorReducer::ReduceInt64Add(Node* node) {
758 : DCHECK_EQ(IrOpcode::kInt64Add, node->opcode());
759 1796593 : Int64BinopMatcher m(node);
760 1796592 : if (m.right().Is(0)) return Replace(m.left().node()); // x + 0 => 0
761 1783736 : if (m.IsFoldable()) {
762 : return ReplaceInt64(
763 78635 : base::AddWithWraparound(m.left().Value(), m.right().Value()));
764 : }
765 : return NoChange();
766 : }
767 :
768 63084 : Reduction MachineOperatorReducer::ReduceInt32Sub(Node* node) {
769 : DCHECK_EQ(IrOpcode::kInt32Sub, node->opcode());
770 63084 : Int32BinopMatcher m(node);
771 63084 : if (m.right().Is(0)) return Replace(m.left().node()); // x - 0 => x
772 62505 : if (m.IsFoldable()) { // K - K => K
773 : return ReplaceInt32(
774 19079 : base::SubWithWraparound(m.left().Value(), m.right().Value()));
775 : }
776 43426 : if (m.LeftEqualsRight()) return ReplaceInt32(0); // x - x => 0
777 43426 : if (m.right().HasValue()) { // x - K => x + -K
778 13681 : node->ReplaceInput(
779 13681 : 1, Int32Constant(base::NegateWithWraparound(m.right().Value())));
780 13681 : NodeProperties::ChangeOp(node, machine()->Int32Add());
781 13681 : Reduction const reduction = ReduceInt32Add(node);
782 13681 : return reduction.Changed() ? reduction : Changed(node);
783 : }
784 : return NoChange();
785 : }
786 :
787 312715 : Reduction MachineOperatorReducer::ReduceInt64Sub(Node* node) {
788 : DCHECK_EQ(IrOpcode::kInt64Sub, node->opcode());
789 312715 : Int64BinopMatcher m(node);
790 312714 : if (m.right().Is(0)) return Replace(m.left().node()); // x - 0 => x
791 306183 : if (m.IsFoldable()) { // K - K => K
792 : return ReplaceInt64(
793 35260 : base::SubWithWraparound(m.left().Value(), m.right().Value()));
794 : }
795 270923 : if (m.LeftEqualsRight()) return Replace(Int64Constant(0)); // x - x => 0
796 270918 : if (m.right().HasValue()) { // x - K => x + -K
797 509442 : node->ReplaceInput(
798 254722 : 1, Int64Constant(base::NegateWithWraparound(m.right().Value())));
799 254722 : NodeProperties::ChangeOp(node, machine()->Int64Add());
800 254722 : Reduction const reduction = ReduceInt64Add(node);
801 254722 : return reduction.Changed() ? reduction : Changed(node);
802 : }
803 : return NoChange();
804 : }
805 :
806 20528 : Reduction MachineOperatorReducer::ReduceInt32Div(Node* node) {
807 20528 : Int32BinopMatcher m(node);
808 20528 : if (m.left().Is(0)) return Replace(m.left().node()); // 0 / x => 0
809 20243 : if (m.right().Is(0)) return Replace(m.right().node()); // x / 0 => 0
810 20242 : if (m.right().Is(1)) return Replace(m.left().node()); // x / 1 => x
811 19922 : if (m.IsFoldable()) { // K / K => K
812 : return ReplaceInt32(
813 15960 : base::bits::SignedDiv32(m.left().Value(), m.right().Value()));
814 : }
815 3962 : if (m.LeftEqualsRight()) { // x / x => x != 0
816 : Node* const zero = Int32Constant(0);
817 1 : return Replace(Word32Equal(Word32Equal(m.left().node(), zero), zero));
818 : }
819 3961 : if (m.right().Is(-1)) { // x / -1 => 0 - x
820 32 : node->ReplaceInput(0, Int32Constant(0));
821 32 : node->ReplaceInput(1, m.left().node());
822 32 : node->TrimInputCount(2);
823 32 : NodeProperties::ChangeOp(node, machine()->Int32Sub());
824 : return Changed(node);
825 : }
826 3929 : if (m.right().HasValue()) {
827 2805 : int32_t const divisor = m.right().Value();
828 : Node* const dividend = m.left().node();
829 : Node* quotient = dividend;
830 2805 : if (base::bits::IsPowerOfTwo(Abs(divisor))) {
831 738 : uint32_t const shift = WhichPowerOf2(Abs(divisor));
832 : DCHECK_NE(0u, shift);
833 738 : if (shift > 1) {
834 632 : quotient = Word32Sar(quotient, 31);
835 : }
836 738 : quotient = Int32Add(Word32Shr(quotient, 32u - shift), dividend);
837 738 : quotient = Word32Sar(quotient, shift);
838 : } else {
839 2067 : quotient = Int32Div(quotient, Abs(divisor));
840 : }
841 2805 : if (divisor < 0) {
842 1278 : node->ReplaceInput(0, Int32Constant(0));
843 1278 : node->ReplaceInput(1, quotient);
844 1278 : node->TrimInputCount(2);
845 1278 : NodeProperties::ChangeOp(node, machine()->Int32Sub());
846 : return Changed(node);
847 : }
848 : return Replace(quotient);
849 : }
850 : return NoChange();
851 : }
852 :
853 :
854 19320 : Reduction MachineOperatorReducer::ReduceUint32Div(Node* node) {
855 19320 : Uint32BinopMatcher m(node);
856 19320 : if (m.left().Is(0)) return Replace(m.left().node()); // 0 / x => 0
857 18974 : if (m.right().Is(0)) return Replace(m.right().node()); // x / 0 => 0
858 18926 : if (m.right().Is(1)) return Replace(m.left().node()); // x / 1 => x
859 18583 : if (m.IsFoldable()) { // K / K => K
860 : return ReplaceUint32(
861 18137 : base::bits::UnsignedDiv32(m.left().Value(), m.right().Value()));
862 : }
863 446 : if (m.LeftEqualsRight()) { // x / x => x != 0
864 : Node* const zero = Int32Constant(0);
865 1 : return Replace(Word32Equal(Word32Equal(m.left().node(), zero), zero));
866 : }
867 445 : if (m.right().HasValue()) {
868 : Node* const dividend = m.left().node();
869 273 : uint32_t const divisor = m.right().Value();
870 273 : if (base::bits::IsPowerOfTwo(divisor)) { // x / 2^n => x >> n
871 432 : node->ReplaceInput(1, Uint32Constant(WhichPowerOf2(m.right().Value())));
872 216 : node->TrimInputCount(2);
873 216 : NodeProperties::ChangeOp(node, machine()->Word32Shr());
874 : return Changed(node);
875 : } else {
876 57 : return Replace(Uint32Div(dividend, divisor));
877 : }
878 : }
879 : return NoChange();
880 : }
881 :
882 :
883 30533 : Reduction MachineOperatorReducer::ReduceInt32Mod(Node* node) {
884 30533 : Int32BinopMatcher m(node);
885 30533 : if (m.left().Is(0)) return Replace(m.left().node()); // 0 % x => 0
886 30146 : if (m.right().Is(0)) return Replace(m.right().node()); // x % 0 => 0
887 30046 : if (m.right().Is(1)) return ReplaceInt32(0); // x % 1 => 0
888 29734 : if (m.right().Is(-1)) return ReplaceInt32(0); // x % -1 => 0
889 29448 : if (m.LeftEqualsRight()) return ReplaceInt32(0); // x % x => 0
890 29447 : if (m.IsFoldable()) { // K % K => K
891 : return ReplaceInt32(
892 25506 : base::bits::SignedMod32(m.left().Value(), m.right().Value()));
893 : }
894 3941 : if (m.right().HasValue()) {
895 : Node* const dividend = m.left().node();
896 2838 : uint32_t const divisor = Abs(m.right().Value());
897 2838 : if (base::bits::IsPowerOfTwo(divisor)) {
898 755 : uint32_t const mask = divisor - 1;
899 : Node* const zero = Int32Constant(0);
900 : Diamond d(graph(), common(),
901 : graph()->NewNode(machine()->Int32LessThan(), dividend, zero),
902 1510 : BranchHint::kFalse);
903 : return Replace(
904 : d.Phi(MachineRepresentation::kWord32,
905 : Int32Sub(zero, Word32And(Int32Sub(zero, dividend), mask)),
906 755 : Word32And(dividend, mask)));
907 : } else {
908 2083 : Node* quotient = Int32Div(dividend, divisor);
909 : DCHECK_EQ(dividend, node->InputAt(0));
910 2083 : node->ReplaceInput(1, Int32Mul(quotient, Int32Constant(divisor)));
911 2083 : node->TrimInputCount(2);
912 2083 : NodeProperties::ChangeOp(node, machine()->Int32Sub());
913 : }
914 : return Changed(node);
915 : }
916 : return NoChange();
917 : }
918 :
919 :
920 21180 : Reduction MachineOperatorReducer::ReduceUint32Mod(Node* node) {
921 21180 : Uint32BinopMatcher m(node);
922 21180 : if (m.left().Is(0)) return Replace(m.left().node()); // 0 % x => 0
923 20800 : if (m.right().Is(0)) return Replace(m.right().node()); // x % 0 => 0
924 20752 : if (m.right().Is(1)) return ReplaceUint32(0); // x % 1 => 0
925 20409 : if (m.LeftEqualsRight()) return ReplaceInt32(0); // x % x => 0
926 20407 : if (m.IsFoldable()) { // K % K => K
927 : return ReplaceUint32(
928 18186 : base::bits::UnsignedMod32(m.left().Value(), m.right().Value()));
929 : }
930 2221 : if (m.right().HasValue()) {
931 : Node* const dividend = m.left().node();
932 1602 : uint32_t const divisor = m.right().Value();
933 1602 : if (base::bits::IsPowerOfTwo(divisor)) { // x % 2^n => x & 2^n-1
934 954 : node->ReplaceInput(1, Uint32Constant(m.right().Value() - 1));
935 477 : node->TrimInputCount(2);
936 477 : NodeProperties::ChangeOp(node, machine()->Word32And());
937 : } else {
938 1125 : Node* quotient = Uint32Div(dividend, divisor);
939 : DCHECK_EQ(dividend, node->InputAt(0));
940 1125 : node->ReplaceInput(1, Int32Mul(quotient, Uint32Constant(divisor)));
941 1125 : node->TrimInputCount(2);
942 1125 : NodeProperties::ChangeOp(node, machine()->Int32Sub());
943 : }
944 : return Changed(node);
945 : }
946 : return NoChange();
947 : }
948 :
949 :
950 3239044 : Reduction MachineOperatorReducer::ReduceStore(Node* node) {
951 : NodeMatcher nm(node);
952 : MachineRepresentation rep;
953 : int value_input;
954 3239044 : if (nm.IsStore()) {
955 3239044 : rep = StoreRepresentationOf(node->op()).representation();
956 : value_input = 2;
957 : } else {
958 : DCHECK(nm.IsUnalignedStore());
959 0 : rep = UnalignedStoreRepresentationOf(node->op());
960 : value_input = 2;
961 : }
962 :
963 : Node* const value = node->InputAt(value_input);
964 :
965 3239048 : switch (value->opcode()) {
966 : case IrOpcode::kWord32And: {
967 7319 : Uint32BinopMatcher m(value);
968 19884 : if (m.right().HasValue() && ((rep == MachineRepresentation::kWord8 &&
969 7133 : (m.right().Value() & 0xFF) == 0xFF) ||
970 1337 : (rep == MachineRepresentation::kWord16 &&
971 1337 : (m.right().Value() & 0xFFFF) == 0xFFFF))) {
972 6305 : node->ReplaceInput(value_input, m.left().node());
973 6305 : return Changed(node);
974 : }
975 1014 : break;
976 : }
977 : case IrOpcode::kWord32Sar: {
978 377 : Int32BinopMatcher m(value);
979 883 : if (m.left().IsWord32Shl() && ((rep == MachineRepresentation::kWord8 &&
980 201 : m.right().IsInRange(1, 24)) ||
981 193 : (rep == MachineRepresentation::kWord16 &&
982 : m.right().IsInRange(1, 16)))) {
983 322 : Int32BinopMatcher mleft(m.left().node());
984 322 : if (mleft.right().Is(m.right().Value())) {
985 322 : node->ReplaceInput(value_input, mleft.left().node());
986 322 : return Changed(node);
987 : }
988 : }
989 55 : break;
990 : }
991 : default:
992 : break;
993 : }
994 : return NoChange();
995 : }
996 :
997 :
998 390535 : Reduction MachineOperatorReducer::ReduceProjection(size_t index, Node* node) {
999 390535 : switch (node->opcode()) {
1000 : case IrOpcode::kInt32AddWithOverflow: {
1001 : DCHECK(index == 0 || index == 1);
1002 260038 : Int32BinopMatcher m(node);
1003 260047 : if (m.IsFoldable()) {
1004 : int32_t val;
1005 20006 : bool ovf = base::bits::SignedAddOverflow32(m.left().Value(),
1006 : m.right().Value(), &val);
1007 20006 : return ReplaceInt32(index == 0 ? val : ovf);
1008 : }
1009 240041 : if (m.right().Is(0)) {
1010 32 : return Replace(index == 0 ? m.left().node() : m.right().node());
1011 : }
1012 240009 : break;
1013 : }
1014 : case IrOpcode::kInt32SubWithOverflow: {
1015 : DCHECK(index == 0 || index == 1);
1016 66794 : Int32BinopMatcher m(node);
1017 66794 : if (m.IsFoldable()) {
1018 : int32_t val;
1019 20056 : bool ovf = base::bits::SignedSubOverflow32(m.left().Value(),
1020 : m.right().Value(), &val);
1021 20056 : return ReplaceInt32(index == 0 ? val : ovf);
1022 : }
1023 46738 : if (m.right().Is(0)) {
1024 2 : return Replace(index == 0 ? m.left().node() : m.right().node());
1025 : }
1026 46736 : break;
1027 : }
1028 : case IrOpcode::kInt32MulWithOverflow: {
1029 : DCHECK(index == 0 || index == 1);
1030 31166 : Int32BinopMatcher m(node);
1031 31166 : if (m.IsFoldable()) {
1032 : int32_t val;
1033 20310 : bool ovf = base::bits::SignedMulOverflow32(m.left().Value(),
1034 20310 : m.right().Value(), &val);
1035 20310 : return ReplaceInt32(index == 0 ? val : ovf);
1036 : }
1037 10856 : if (m.right().Is(0)) {
1038 : return Replace(m.right().node());
1039 : }
1040 10770 : if (m.right().Is(1)) {
1041 72 : return index == 0 ? Replace(m.left().node()) : ReplaceInt32(0);
1042 : }
1043 10698 : break;
1044 : }
1045 : default:
1046 : break;
1047 : }
1048 : return NoChange();
1049 : }
1050 :
1051 :
1052 116148 : Reduction MachineOperatorReducer::ReduceWord32Shifts(Node* node) {
1053 : DCHECK((node->opcode() == IrOpcode::kWord32Shl) ||
1054 : (node->opcode() == IrOpcode::kWord32Shr) ||
1055 : (node->opcode() == IrOpcode::kWord32Sar));
1056 116148 : if (machine()->Word32ShiftIsSafe()) {
1057 : // Remove the explicit 'and' with 0x1F if the shift provided by the machine
1058 : // instruction matches that required by JavaScript.
1059 115833 : Int32BinopMatcher m(node);
1060 115833 : if (m.right().IsWord32And()) {
1061 1770 : Int32BinopMatcher mright(m.right().node());
1062 1770 : if (mright.right().Is(0x1F)) {
1063 787 : node->ReplaceInput(1, mright.left().node());
1064 787 : return Changed(node);
1065 : }
1066 : }
1067 : }
1068 : return NoChange();
1069 : }
1070 :
1071 :
1072 43364 : Reduction MachineOperatorReducer::ReduceWord32Shl(Node* node) {
1073 : DCHECK_EQ(IrOpcode::kWord32Shl, node->opcode());
1074 43364 : Int32BinopMatcher m(node);
1075 43364 : if (m.right().Is(0)) return Replace(m.left().node()); // x << 0 => x
1076 42988 : if (m.IsFoldable()) { // K << K => K
1077 : return ReplaceInt32(
1078 11799 : base::ShlWithWraparound(m.left().Value(), m.right().Value()));
1079 : }
1080 31189 : if (m.right().IsInRange(1, 31)) {
1081 : // (x >>> K) << K => x & ~(2^K - 1)
1082 : // (x >> K) << K => x & ~(2^K - 1)
1083 27674 : if (m.left().IsWord32Sar() || m.left().IsWord32Shr()) {
1084 3985 : Int32BinopMatcher mleft(m.left().node());
1085 3985 : if (mleft.right().Is(m.right().Value())) {
1086 3057 : node->ReplaceInput(0, mleft.left().node());
1087 3057 : node->ReplaceInput(1,
1088 6114 : Uint32Constant(~((1U << m.right().Value()) - 1U)));
1089 3057 : NodeProperties::ChangeOp(node, machine()->Word32And());
1090 3057 : Reduction reduction = ReduceWord32And(node);
1091 3057 : return reduction.Changed() ? reduction : Changed(node);
1092 : }
1093 : }
1094 : }
1095 28132 : return ReduceWord32Shifts(node);
1096 : }
1097 :
1098 697362 : Reduction MachineOperatorReducer::ReduceWord64Shl(Node* node) {
1099 : DCHECK_EQ(IrOpcode::kWord64Shl, node->opcode());
1100 697362 : Int64BinopMatcher m(node);
1101 697362 : if (m.right().Is(0)) return Replace(m.left().node()); // x << 0 => x
1102 696952 : if (m.IsFoldable()) { // K << K => K
1103 : return ReplaceInt64(
1104 89809 : base::ShlWithWraparound(m.left().Value(), m.right().Value()));
1105 : }
1106 : return NoChange();
1107 : }
1108 :
1109 80421 : Reduction MachineOperatorReducer::ReduceWord32Shr(Node* node) {
1110 80421 : Uint32BinopMatcher m(node);
1111 80421 : if (m.right().Is(0)) return Replace(m.left().node()); // x >>> 0 => x
1112 67797 : if (m.IsFoldable()) { // K >>> K => K
1113 9090 : return ReplaceInt32(m.left().Value() >> (m.right().Value() & 31));
1114 : }
1115 58707 : if (m.left().IsWord32And() && m.right().HasValue()) {
1116 24375 : Uint32BinopMatcher mleft(m.left().node());
1117 24375 : if (mleft.right().HasValue()) {
1118 24375 : uint32_t shift = m.right().Value() & 31;
1119 24375 : uint32_t mask = mleft.right().Value();
1120 24375 : if ((mask >> shift) == 0) {
1121 : // (m >>> s) == 0 implies ((x & m) >>> s) == 0
1122 31 : return ReplaceInt32(0);
1123 : }
1124 : }
1125 : }
1126 58676 : return ReduceWord32Shifts(node);
1127 : }
1128 :
1129 50050 : Reduction MachineOperatorReducer::ReduceWord64Shr(Node* node) {
1130 : DCHECK_EQ(IrOpcode::kWord64Shr, node->opcode());
1131 50050 : Uint64BinopMatcher m(node);
1132 50050 : if (m.right().Is(0)) return Replace(m.left().node()); // x >>> 0 => x
1133 49640 : if (m.IsFoldable()) { // K >> K => K
1134 25515 : return ReplaceInt64(m.left().Value() >> (m.right().Value() & 63));
1135 : }
1136 : return NoChange();
1137 : }
1138 :
1139 39186 : Reduction MachineOperatorReducer::ReduceWord32Sar(Node* node) {
1140 39186 : Int32BinopMatcher m(node);
1141 39186 : if (m.right().Is(0)) return Replace(m.left().node()); // x >> 0 => x
1142 38760 : if (m.IsFoldable()) { // K >> K => K
1143 9369 : return ReplaceInt32(m.left().Value() >> (m.right().Value() & 31));
1144 : }
1145 29391 : if (m.left().IsWord32Shl()) {
1146 1248 : Int32BinopMatcher mleft(m.left().node());
1147 1248 : if (mleft.left().IsComparison()) {
1148 98 : if (m.right().Is(31) && mleft.right().Is(31)) {
1149 : // Comparison << 31 >> 31 => 0 - Comparison
1150 49 : node->ReplaceInput(0, Int32Constant(0));
1151 49 : node->ReplaceInput(1, mleft.left().node());
1152 49 : NodeProperties::ChangeOp(node, machine()->Int32Sub());
1153 49 : Reduction const reduction = ReduceInt32Sub(node);
1154 49 : return reduction.Changed() ? reduction : Changed(node);
1155 : }
1156 1199 : } else if (mleft.left().IsLoad()) {
1157 : LoadRepresentation const rep =
1158 2 : LoadRepresentationOf(mleft.left().node()->op());
1159 4 : if (m.right().Is(24) && mleft.right().Is(24) &&
1160 : rep == MachineType::Int8()) {
1161 : // Load[kMachInt8] << 24 >> 24 => Load[kMachInt8]
1162 : return Replace(mleft.left().node());
1163 : }
1164 3 : if (m.right().Is(16) && mleft.right().Is(16) &&
1165 : rep == MachineType::Int16()) {
1166 : // Load[kMachInt16] << 16 >> 16 => Load[kMachInt8]
1167 : return Replace(mleft.left().node());
1168 : }
1169 : }
1170 : }
1171 29340 : return ReduceWord32Shifts(node);
1172 : }
1173 :
1174 477252 : Reduction MachineOperatorReducer::ReduceWord64Sar(Node* node) {
1175 477252 : Int64BinopMatcher m(node);
1176 477254 : if (m.right().Is(0)) return Replace(m.left().node()); // x >> 0 => x
1177 476844 : if (m.IsFoldable()) {
1178 34328 : return ReplaceInt64(m.left().Value() >> (m.right().Value() & 63));
1179 : }
1180 : return NoChange();
1181 : }
1182 :
1183 765967 : Reduction MachineOperatorReducer::ReduceWord32And(Node* node) {
1184 : DCHECK_EQ(IrOpcode::kWord32And, node->opcode());
1185 765967 : Int32BinopMatcher m(node);
1186 765967 : if (m.right().Is(0)) return Replace(m.right().node()); // x & 0 => 0
1187 764266 : if (m.right().Is(-1)) return Replace(m.left().node()); // x & -1 => x
1188 765020 : if (m.left().IsComparison() && m.right().Is(1)) { // CMP & 1 => CMP
1189 : return Replace(m.left().node());
1190 : }
1191 763670 : if (m.IsFoldable()) { // K & K => K
1192 23112 : return ReplaceInt32(m.left().Value() & m.right().Value());
1193 : }
1194 740558 : if (m.LeftEqualsRight()) return Replace(m.left().node()); // x & x => x
1195 740473 : if (m.left().IsWord32And() && m.right().HasValue()) {
1196 30537 : Int32BinopMatcher mleft(m.left().node());
1197 30537 : if (mleft.right().HasValue()) { // (x & K) & K => x & K
1198 19698 : node->ReplaceInput(0, mleft.left().node());
1199 19698 : node->ReplaceInput(
1200 19698 : 1, Int32Constant(m.right().Value() & mleft.right().Value()));
1201 19698 : Reduction const reduction = ReduceWord32And(node);
1202 19698 : return reduction.Changed() ? reduction : Changed(node);
1203 : }
1204 : }
1205 720775 : if (m.right().IsNegativePowerOf2()) {
1206 257188 : int32_t const mask = m.right().Value();
1207 : int32_t const neg_mask = base::NegateWithWraparound(mask);
1208 257188 : if (m.left().IsWord32Shl()) {
1209 2142 : Uint32BinopMatcher mleft(m.left().node());
1210 4284 : if (mleft.right().HasValue() &&
1211 2142 : (mleft.right().Value() & 0x1F) >=
1212 : base::bits::CountTrailingZeros(mask)) {
1213 : // (x << L) & (-1 << K) => x << L iff L >= K
1214 2140 : return Replace(mleft.node());
1215 : }
1216 255046 : } else if (m.left().IsInt32Add()) {
1217 94806 : Int32BinopMatcher mleft(m.left().node());
1218 169547 : if (mleft.right().HasValue() &&
1219 74741 : (mleft.right().Value() & mask) == mleft.right().Value()) {
1220 : // (x + (K << L)) & (-1 << L) => (x & (-1 << L)) + (K << L)
1221 74582 : node->ReplaceInput(0, Word32And(mleft.left().node(), m.right().node()));
1222 74582 : node->ReplaceInput(1, mleft.right().node());
1223 74582 : NodeProperties::ChangeOp(node, machine()->Int32Add());
1224 74582 : Reduction const reduction = ReduceInt32Add(node);
1225 74582 : return reduction.Changed() ? reduction : Changed(node);
1226 : }
1227 20224 : if (mleft.left().IsInt32Mul()) {
1228 2924 : Int32BinopMatcher mleftleft(mleft.left().node());
1229 2924 : if (mleftleft.right().IsMultipleOf(neg_mask)) {
1230 : // (y * (K << L) + x) & (-1 << L) => (x & (-1 << L)) + y * (K << L)
1231 2923 : node->ReplaceInput(0,
1232 2923 : Word32And(mleft.right().node(), m.right().node()));
1233 2923 : node->ReplaceInput(1, mleftleft.node());
1234 2923 : NodeProperties::ChangeOp(node, machine()->Int32Add());
1235 2923 : Reduction const reduction = ReduceInt32Add(node);
1236 2923 : return reduction.Changed() ? reduction : Changed(node);
1237 : }
1238 : }
1239 17301 : if (mleft.right().IsInt32Mul()) {
1240 7153 : Int32BinopMatcher mleftright(mleft.right().node());
1241 7153 : if (mleftright.right().IsMultipleOf(neg_mask)) {
1242 : // (x + y * (K << L)) & (-1 << L) => (x & (-1 << L)) + y * (K << L)
1243 7143 : node->ReplaceInput(0,
1244 7143 : Word32And(mleft.left().node(), m.right().node()));
1245 7143 : node->ReplaceInput(1, mleftright.node());
1246 7143 : NodeProperties::ChangeOp(node, machine()->Int32Add());
1247 7143 : Reduction const reduction = ReduceInt32Add(node);
1248 7143 : return reduction.Changed() ? reduction : Changed(node);
1249 : }
1250 : }
1251 10158 : if (mleft.left().IsWord32Shl()) {
1252 36 : Int32BinopMatcher mleftleft(mleft.left().node());
1253 72 : if (mleftleft.right().Is(base::bits::CountTrailingZeros(mask))) {
1254 : // (y << L + x) & (-1 << L) => (x & (-1 << L)) + y << L
1255 31 : node->ReplaceInput(0,
1256 31 : Word32And(mleft.right().node(), m.right().node()));
1257 31 : node->ReplaceInput(1, mleftleft.node());
1258 31 : NodeProperties::ChangeOp(node, machine()->Int32Add());
1259 31 : Reduction const reduction = ReduceInt32Add(node);
1260 31 : return reduction.Changed() ? reduction : Changed(node);
1261 : }
1262 : }
1263 10127 : if (mleft.right().IsWord32Shl()) {
1264 6360 : Int32BinopMatcher mleftright(mleft.right().node());
1265 12720 : if (mleftright.right().Is(base::bits::CountTrailingZeros(mask))) {
1266 : // (x + y << L) & (-1 << L) => (x & (-1 << L)) + y << L
1267 2425 : node->ReplaceInput(0,
1268 2425 : Word32And(mleft.left().node(), m.right().node()));
1269 2425 : node->ReplaceInput(1, mleftright.node());
1270 2425 : NodeProperties::ChangeOp(node, machine()->Int32Add());
1271 2425 : Reduction const reduction = ReduceInt32Add(node);
1272 2425 : return reduction.Changed() ? reduction : Changed(node);
1273 : }
1274 : }
1275 160240 : } else if (m.left().IsInt32Mul()) {
1276 5892 : Int32BinopMatcher mleft(m.left().node());
1277 5892 : if (mleft.right().IsMultipleOf(neg_mask)) {
1278 : // (x * (K << L)) & (-1 << L) => x * (K << L)
1279 5892 : return Replace(mleft.node());
1280 : }
1281 : }
1282 : }
1283 : return NoChange();
1284 : }
1285 :
1286 52730 : Reduction MachineOperatorReducer::TryMatchWord32Ror(Node* node) {
1287 : DCHECK(IrOpcode::kWord32Or == node->opcode() ||
1288 : IrOpcode::kWord32Xor == node->opcode());
1289 52730 : Int32BinopMatcher m(node);
1290 : Node* shl = nullptr;
1291 : Node* shr = nullptr;
1292 : // Recognize rotation, we are matching:
1293 : // * x << y | x >>> (32 - y) => x ror (32 - y), i.e x rol y
1294 : // * x << (32 - y) | x >>> y => x ror y
1295 : // * x << y ^ x >>> (32 - y) => x ror (32 - y), i.e. x rol y
1296 : // * x << (32 - y) ^ x >>> y => x ror y
1297 : // as well as their commuted form.
1298 59650 : if (m.left().IsWord32Shl() && m.right().IsWord32Shr()) {
1299 : shl = m.left().node();
1300 : shr = m.right().node();
1301 52251 : } else if (m.left().IsWord32Shr() && m.right().IsWord32Shl()) {
1302 : shl = m.right().node();
1303 : shr = m.left().node();
1304 : } else {
1305 : return NoChange();
1306 : }
1307 :
1308 940 : Int32BinopMatcher mshl(shl);
1309 940 : Int32BinopMatcher mshr(shr);
1310 940 : if (mshl.left().node() != mshr.left().node()) return NoChange();
1311 :
1312 639 : if (mshl.right().HasValue() && mshr.right().HasValue()) {
1313 : // Case where y is a constant.
1314 382 : if (mshl.right().Value() + mshr.right().Value() != 32) return NoChange();
1315 : } else {
1316 : Node* sub = nullptr;
1317 : Node* y = nullptr;
1318 257 : if (mshl.right().IsInt32Sub()) {
1319 : sub = mshl.right().node();
1320 : y = mshr.right().node();
1321 214 : } else if (mshr.right().IsInt32Sub()) {
1322 : sub = mshr.right().node();
1323 : y = mshl.right().node();
1324 : } else {
1325 185 : return NoChange();
1326 : }
1327 :
1328 128 : Int32BinopMatcher msub(sub);
1329 256 : if (!msub.left().Is(32) || msub.right().node() != y) return NoChange();
1330 : }
1331 :
1332 454 : node->ReplaceInput(0, mshl.left().node());
1333 454 : node->ReplaceInput(1, mshr.right().node());
1334 454 : NodeProperties::ChangeOp(node, machine()->Word32Ror());
1335 : return Changed(node);
1336 : }
1337 :
1338 80866 : Reduction MachineOperatorReducer::ReduceWord32Or(Node* node) {
1339 : DCHECK_EQ(IrOpcode::kWord32Or, node->opcode());
1340 80866 : Int32BinopMatcher m(node);
1341 80866 : if (m.right().Is(0)) return Replace(m.left().node()); // x | 0 => x
1342 66062 : if (m.right().Is(-1)) return Replace(m.right().node()); // x | -1 => -1
1343 62660 : if (m.IsFoldable()) { // K | K => K
1344 16315 : return ReplaceInt32(m.left().Value() | m.right().Value());
1345 : }
1346 46345 : if (m.LeftEqualsRight()) return Replace(m.left().node()); // x | x => x
1347 :
1348 46314 : return TryMatchWord32Ror(node);
1349 : }
1350 :
1351 23381 : Reduction MachineOperatorReducer::ReduceWord32Xor(Node* node) {
1352 : DCHECK_EQ(IrOpcode::kWord32Xor, node->opcode());
1353 23381 : Int32BinopMatcher m(node);
1354 23381 : if (m.right().Is(0)) return Replace(m.left().node()); // x ^ 0 => x
1355 23056 : if (m.IsFoldable()) { // K ^ K => K
1356 16615 : return ReplaceInt32(m.left().Value() ^ m.right().Value());
1357 : }
1358 6441 : if (m.LeftEqualsRight()) return ReplaceInt32(0); // x ^ x => 0
1359 6730 : if (m.left().IsWord32Xor() && m.right().Is(-1)) {
1360 20 : Int32BinopMatcher mleft(m.left().node());
1361 20 : if (mleft.right().Is(-1)) { // (x ^ -1) ^ -1 => x
1362 20 : return Replace(mleft.left().node());
1363 : }
1364 : }
1365 :
1366 6416 : return TryMatchWord32Ror(node);
1367 : }
1368 :
1369 4856 : Reduction MachineOperatorReducer::ReduceFloat64InsertLowWord32(Node* node) {
1370 : DCHECK_EQ(IrOpcode::kFloat64InsertLowWord32, node->opcode());
1371 : Float64Matcher mlhs(node->InputAt(0));
1372 : Uint32Matcher mrhs(node->InputAt(1));
1373 4856 : if (mlhs.HasValue() && mrhs.HasValue()) {
1374 : return ReplaceFloat64(bit_cast<double>(
1375 4800 : (bit_cast<uint64_t>(mlhs.Value()) & uint64_t{0xFFFFFFFF00000000}) |
1376 : mrhs.Value()));
1377 : }
1378 : return NoChange();
1379 : }
1380 :
1381 :
1382 4856 : Reduction MachineOperatorReducer::ReduceFloat64InsertHighWord32(Node* node) {
1383 : DCHECK_EQ(IrOpcode::kFloat64InsertHighWord32, node->opcode());
1384 : Float64Matcher mlhs(node->InputAt(0));
1385 : Uint32Matcher mrhs(node->InputAt(1));
1386 4856 : if (mlhs.HasValue() && mrhs.HasValue()) {
1387 : return ReplaceFloat64(bit_cast<double>(
1388 9600 : (bit_cast<uint64_t>(mlhs.Value()) & uint64_t{0xFFFFFFFF}) |
1389 4800 : (static_cast<uint64_t>(mrhs.Value()) << 32)));
1390 : }
1391 : return NoChange();
1392 : }
1393 :
1394 :
1395 : namespace {
1396 :
1397 : bool IsFloat64RepresentableAsFloat32(const Float64Matcher& m) {
1398 328554 : if (m.HasValue()) {
1399 104313 : double v = m.Value();
1400 104313 : return DoubleToFloat32(v) == v;
1401 : }
1402 : return false;
1403 : }
1404 :
1405 : } // namespace
1406 :
1407 :
1408 360813 : Reduction MachineOperatorReducer::ReduceFloat64Compare(Node* node) {
1409 : DCHECK(IrOpcode::kFloat64Equal == node->opcode() ||
1410 : IrOpcode::kFloat64LessThan == node->opcode() ||
1411 : IrOpcode::kFloat64LessThanOrEqual == node->opcode());
1412 360813 : Float64BinopMatcher m(node);
1413 360813 : if (m.IsFoldable()) {
1414 32513 : switch (node->opcode()) {
1415 : case IrOpcode::kFloat64Equal:
1416 11685 : return ReplaceBool(m.left().Value() == m.right().Value());
1417 : case IrOpcode::kFloat64LessThan:
1418 10701 : return ReplaceBool(m.left().Value() < m.right().Value());
1419 : case IrOpcode::kFloat64LessThanOrEqual:
1420 10127 : return ReplaceBool(m.left().Value() <= m.right().Value());
1421 : default:
1422 0 : UNREACHABLE();
1423 : }
1424 329986 : } else if ((m.left().IsChangeFloat32ToFloat64() &&
1425 327773 : m.right().IsChangeFloat32ToFloat64()) ||
1426 1159 : (m.left().IsChangeFloat32ToFloat64() &&
1427 655695 : IsFloat64RepresentableAsFloat32(m.right())) ||
1428 103829 : (IsFloat64RepresentableAsFloat32(m.left()) &&
1429 : m.right().IsChangeFloat32ToFloat64())) {
1430 : // As all Float32 values have an exact representation in Float64, comparing
1431 : // two Float64 values both converted from Float32 is equivalent to comparing
1432 : // the original Float32s, so we can ignore the conversions. We can also
1433 : // reduce comparisons of converted Float64 values against constants that
1434 : // can be represented exactly as Float32.
1435 1145 : switch (node->opcode()) {
1436 : case IrOpcode::kFloat64Equal:
1437 286 : NodeProperties::ChangeOp(node, machine()->Float32Equal());
1438 286 : break;
1439 : case IrOpcode::kFloat64LessThan:
1440 583 : NodeProperties::ChangeOp(node, machine()->Float32LessThan());
1441 583 : break;
1442 : case IrOpcode::kFloat64LessThanOrEqual:
1443 276 : NodeProperties::ChangeOp(node, machine()->Float32LessThanOrEqual());
1444 276 : break;
1445 : default:
1446 0 : UNREACHABLE();
1447 : }
1448 1385 : node->ReplaceInput(
1449 : 0, m.left().HasValue()
1450 240 : ? Float32Constant(static_cast<float>(m.left().Value()))
1451 1145 : : m.left().InputAt(0));
1452 1523 : node->ReplaceInput(
1453 : 1, m.right().HasValue()
1454 378 : ? Float32Constant(static_cast<float>(m.right().Value()))
1455 1145 : : m.right().InputAt(0));
1456 : return Changed(node);
1457 : }
1458 : return NoChange();
1459 : }
1460 :
1461 81772 : Reduction MachineOperatorReducer::ReduceFloat64RoundDown(Node* node) {
1462 : DCHECK_EQ(IrOpcode::kFloat64RoundDown, node->opcode());
1463 : Float64Matcher m(node->InputAt(0));
1464 81772 : if (m.HasValue()) {
1465 345 : return ReplaceFloat64(std::floor(m.Value()));
1466 : }
1467 : return NoChange();
1468 : }
1469 :
1470 0 : CommonOperatorBuilder* MachineOperatorReducer::common() const {
1471 0 : return mcgraph()->common();
1472 : }
1473 :
1474 :
1475 0 : MachineOperatorBuilder* MachineOperatorReducer::machine() const {
1476 0 : return mcgraph()->machine();
1477 : }
1478 :
1479 0 : Graph* MachineOperatorReducer::graph() const { return mcgraph()->graph(); }
1480 :
1481 : } // namespace compiler
1482 : } // namespace internal
1483 122036 : } // namespace v8
|