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 1684881 : MachineOperatorReducer::MachineOperatorReducer(Editor* editor,
24 : MachineGraph* mcgraph,
25 : bool allow_signalling_nan)
26 : : AdvancedReducer(editor),
27 : mcgraph_(mcgraph),
28 1684881 : allow_signalling_nan_(allow_signalling_nan) {}
29 :
30 : MachineOperatorReducer::~MachineOperatorReducer() = default;
31 :
32 :
33 66847 : Node* MachineOperatorReducer::Float32Constant(volatile float value) {
34 133694 : return graph()->NewNode(common()->Float32Constant(value));
35 : }
36 :
37 :
38 0 : Node* MachineOperatorReducer::Float64Constant(volatile double value) {
39 97070 : return mcgraph()->Float64Constant(value);
40 : }
41 :
42 :
43 0 : Node* MachineOperatorReducer::Int32Constant(int32_t value) {
44 642715 : return mcgraph()->Int32Constant(value);
45 : }
46 :
47 :
48 566771 : Node* MachineOperatorReducer::Int64Constant(int64_t value) {
49 1133543 : 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 88624 : Node* MachineOperatorReducer::Word32And(Node* lhs, Node* rhs) {
68 88624 : Node* const node = graph()->NewNode(machine()->Word32And(), lhs, rhs);
69 88624 : Reduction const reduction = ReduceWord32And(node);
70 88624 : return reduction.Changed() ? reduction.replacement() : node;
71 : }
72 :
73 :
74 5550 : Node* MachineOperatorReducer::Word32Sar(Node* lhs, uint32_t rhs) {
75 5550 : if (rhs == 0) return lhs;
76 10778 : return graph()->NewNode(machine()->Word32Sar(), lhs, Uint32Constant(rhs));
77 : }
78 :
79 :
80 7714 : Node* MachineOperatorReducer::Word32Shr(Node* lhs, uint32_t rhs) {
81 7714 : if (rhs == 0) return lhs;
82 13318 : return graph()->NewNode(machine()->Word32Shr(), lhs, Uint32Constant(rhs));
83 : }
84 :
85 :
86 12 : Node* MachineOperatorReducer::Word32Equal(Node* lhs, Node* rhs) {
87 24 : return graph()->NewNode(machine()->Word32Equal(), lhs, rhs);
88 : }
89 :
90 :
91 6217 : Node* MachineOperatorReducer::Int32Add(Node* lhs, Node* rhs) {
92 6217 : Node* const node = graph()->NewNode(machine()->Int32Add(), lhs, rhs);
93 6217 : Reduction const reduction = ReduceInt32Add(node);
94 6217 : return reduction.Changed() ? reduction.replacement() : node;
95 : }
96 :
97 :
98 1544 : Node* MachineOperatorReducer::Int32Sub(Node* lhs, Node* rhs) {
99 1544 : Node* const node = graph()->NewNode(machine()->Int32Sub(), lhs, rhs);
100 1544 : Reduction const reduction = ReduceInt32Sub(node);
101 1544 : return reduction.Changed() ? reduction.replacement() : node;
102 : }
103 :
104 :
105 3419 : Node* MachineOperatorReducer::Int32Mul(Node* lhs, Node* rhs) {
106 6838 : return graph()->NewNode(machine()->Int32Mul(), lhs, rhs);
107 : }
108 :
109 :
110 4166 : 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 4166 : base::SignedDivisionByConstant(bit_cast<uint32_t>(divisor));
115 4166 : Node* quotient = graph()->NewNode(machine()->Int32MulHigh(), dividend,
116 : Uint32Constant(mag.multiplier));
117 4166 : if (divisor > 0 && bit_cast<int32_t>(mag.multiplier) < 0) {
118 1281 : quotient = Int32Add(quotient, dividend);
119 2885 : } else if (divisor < 0 && bit_cast<int32_t>(mag.multiplier) > 0) {
120 0 : quotient = Int32Sub(quotient, dividend);
121 : }
122 4166 : return Int32Add(Word32Sar(quotient, mag.shift), Word32Shr(dividend, 31));
123 : }
124 :
125 :
126 1389 : 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 1389 : dividend = Word32Shr(dividend, shift);
132 1389 : divisor >>= shift;
133 : // Compute the magic number for the (shifted) divisor.
134 : base::MagicNumbersForDivision<uint32_t> const mag =
135 1389 : base::UnsignedDivisionByConstant(divisor, shift);
136 1389 : Node* quotient = graph()->NewNode(machine()->Uint32MulHigh(), dividend,
137 1389 : Uint32Constant(mag.multiplier));
138 1389 : 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 1365 : quotient = Word32Shr(quotient, mag.shift);
145 : }
146 1389 : return quotient;
147 : }
148 :
149 :
150 : // Perform constant folding and strength reduction on machine operators.
151 126092041 : Reduction MachineOperatorReducer::Reduce(Node* node) {
152 126092041 : switch (node->opcode()) {
153 : case IrOpcode::kProjection:
154 442055 : return ReduceProjection(ProjectionIndexOf(node->op()), node->InputAt(0));
155 : case IrOpcode::kWord32And:
156 510470 : return ReduceWord32And(node);
157 : case IrOpcode::kWord32Or:
158 112400 : return ReduceWord32Or(node);
159 : case IrOpcode::kWord32Xor:
160 24267 : return ReduceWord32Xor(node);
161 : case IrOpcode::kWord32Shl:
162 69405 : return ReduceWord32Shl(node);
163 : case IrOpcode::kWord64Shl:
164 553599 : return ReduceWord64Shl(node);
165 : case IrOpcode::kWord32Shr:
166 76143 : return ReduceWord32Shr(node);
167 : case IrOpcode::kWord64Shr:
168 49826 : return ReduceWord64Shr(node);
169 : case IrOpcode::kWord32Sar:
170 188114 : return ReduceWord32Sar(node);
171 : case IrOpcode::kWord64Sar:
172 253821 : return ReduceWord64Sar(node);
173 : case IrOpcode::kWord32Ror: {
174 1859 : Int32BinopMatcher m(node);
175 3403 : if (m.right().Is(0)) return Replace(m.left().node()); // x ror 0 => x
176 1810 : 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 315 : break;
181 : }
182 : case IrOpcode::kWord32Equal: {
183 945926 : Int32BinopMatcher m(node);
184 945926 : if (m.IsFoldable()) { // K == K => K
185 69980 : return ReplaceBool(m.left().Value() == m.right().Value());
186 : }
187 912948 : if (m.left().IsInt32Sub() && m.right().Is(0)) { // x - y == 0 => x == y
188 1150 : Int32BinopMatcher msub(m.left().node());
189 1150 : node->ReplaceInput(0, msub.left().node());
190 1150 : node->ReplaceInput(1, msub.right().node());
191 : return Changed(node);
192 : }
193 : // TODO(turbofan): fold HeapConstant, ExternalReference, pointer compares
194 910373 : if (m.LeftEqualsRight()) return ReplaceBool(true); // x == x => true
195 910349 : break;
196 : }
197 : case IrOpcode::kWord64Equal: {
198 1969939 : Int64BinopMatcher m(node);
199 1969943 : if (m.IsFoldable()) { // K == K => K
200 10541 : return ReplaceBool(m.left().Value() == m.right().Value());
201 : }
202 1975197 : if (m.left().IsInt64Sub() && m.right().Is(0)) { // x - y == 0 => x == y
203 392 : Int64BinopMatcher msub(m.left().node());
204 392 : node->ReplaceInput(0, msub.left().node());
205 392 : node->ReplaceInput(1, msub.right().node());
206 : return Changed(node);
207 : }
208 : // TODO(turbofan): fold HeapConstant, ExternalReference, pointer compares
209 1969057 : if (m.LeftEqualsRight()) return ReplaceBool(true); // x == x => true
210 1959896 : break;
211 : }
212 : case IrOpcode::kInt32Add:
213 434774 : return ReduceInt32Add(node);
214 : case IrOpcode::kInt64Add:
215 1689472 : return ReduceInt64Add(node);
216 : case IrOpcode::kInt32Sub:
217 68398 : return ReduceInt32Sub(node);
218 : case IrOpcode::kInt64Sub:
219 329679 : return ReduceInt64Sub(node);
220 : case IrOpcode::kInt32Mul: {
221 42415 : Int32BinopMatcher m(node);
222 63162 : if (m.right().Is(0)) return Replace(m.right().node()); // x * 0 => 0
223 42050 : if (m.right().Is(1)) return Replace(m.left().node()); // x * 1 => x
224 41749 : if (m.IsFoldable()) { // K * K => K
225 : return ReplaceInt32(
226 18079 : base::MulWithWraparound(m.left().Value(), m.right().Value()));
227 : }
228 23670 : if (m.right().Is(-1)) { // x * -1 => 0 - x
229 65 : node->ReplaceInput(0, Int32Constant(0));
230 65 : node->ReplaceInput(1, m.left().node());
231 65 : NodeProperties::ChangeOp(node, machine()->Int32Sub());
232 : return Changed(node);
233 : }
234 23605 : if (m.right().IsPowerOf2()) { // x * 2^n => x << n
235 3874 : node->ReplaceInput(1, Int32Constant(WhichPowerOf2(m.right().Value())));
236 1937 : NodeProperties::ChangeOp(node, machine()->Word32Shl());
237 1937 : Reduction reduction = ReduceWord32Shl(node);
238 1937 : return reduction.Changed() ? reduction : Changed(node);
239 : }
240 21668 : break;
241 : }
242 : case IrOpcode::kInt32MulWithOverflow: {
243 6172 : Int32BinopMatcher m(node);
244 6172 : if (m.right().Is(2)) {
245 389 : node->ReplaceInput(1, m.left().node());
246 389 : NodeProperties::ChangeOp(node, machine()->Int32AddWithOverflow());
247 2671 : return Changed(node);
248 : }
249 5783 : if (m.right().Is(-1)) {
250 2282 : node->ReplaceInput(0, Int32Constant(0));
251 2282 : node->ReplaceInput(1, m.left().node());
252 2282 : NodeProperties::ChangeOp(node, machine()->Int32SubWithOverflow());
253 : return Changed(node);
254 : }
255 3501 : break;
256 : }
257 : case IrOpcode::kInt32Div:
258 20264 : return ReduceInt32Div(node);
259 : case IrOpcode::kUint32Div:
260 19316 : return ReduceUint32Div(node);
261 : case IrOpcode::kInt32Mod:
262 30610 : return ReduceInt32Mod(node);
263 : case IrOpcode::kUint32Mod:
264 21244 : return ReduceUint32Mod(node);
265 : case IrOpcode::kInt32LessThan: {
266 282336 : Int32BinopMatcher m(node);
267 282353 : if (m.IsFoldable()) { // K < K => K
268 38959 : return ReplaceBool(m.left().Value() < m.right().Value());
269 : }
270 262914 : if (m.LeftEqualsRight()) return ReplaceBool(false); // x < x => false
271 264265 : if (m.left().IsWord32Or() && m.right().Is(0)) {
272 : // (x | K) < 0 => true or (K | x) < 0 => true iff K < 0
273 1327 : Int32BinopMatcher mleftmatcher(m.left().node());
274 2654 : if (mleftmatcher.left().IsNegative() ||
275 : mleftmatcher.right().IsNegative()) {
276 69 : return ReplaceBool(true);
277 : }
278 : }
279 262833 : break;
280 : }
281 : case IrOpcode::kInt32LessThanOrEqual: {
282 55726 : Int32BinopMatcher m(node);
283 55726 : if (m.IsFoldable()) { // K <= K => K
284 35783 : return ReplaceBool(m.left().Value() <= m.right().Value());
285 : }
286 37837 : if (m.LeftEqualsRight()) return ReplaceBool(true); // x <= x => true
287 37832 : break;
288 : }
289 : case IrOpcode::kUint32LessThan: {
290 205414 : Uint32BinopMatcher m(node);
291 227685 : if (m.left().Is(kMaxUInt32)) return ReplaceBool(false); // M < x => false
292 205103 : if (m.right().Is(0)) return ReplaceBool(false); // x < 0 => false
293 204682 : if (m.IsFoldable()) { // K < K => K
294 20455 : return ReplaceBool(m.left().Value() < m.right().Value());
295 : }
296 184227 : if (m.LeftEqualsRight()) return ReplaceBool(false); // x < x => false
297 184090 : if (m.left().IsWord32Sar() && m.right().HasValue()) {
298 1042 : Int32BinopMatcher mleft(m.left().node());
299 1042 : if (mleft.right().HasValue()) {
300 : // (x >> K) < C => x < (C << K)
301 : // when C < (M >> K)
302 1042 : const uint32_t c = m.right().Value();
303 1042 : const uint32_t k = mleft.right().Value() & 0x1F;
304 1042 : if (c < static_cast<uint32_t>(kMaxInt >> k)) {
305 947 : node->ReplaceInput(0, mleft.left().node());
306 1894 : node->ReplaceInput(1, Uint32Constant(c << k));
307 947 : return Changed(node);
308 : }
309 : // TODO(turbofan): else the comparison is always true.
310 : }
311 : }
312 183143 : break;
313 : }
314 : case IrOpcode::kUint32LessThanOrEqual: {
315 60849 : Uint32BinopMatcher m(node);
316 78036 : if (m.left().Is(0)) return ReplaceBool(true); // 0 <= x => true
317 60413 : if (m.right().Is(kMaxUInt32)) return ReplaceBool(true); // x <= M => true
318 60123 : if (m.IsFoldable()) { // K <= K => K
319 16455 : return ReplaceBool(m.left().Value() <= m.right().Value());
320 : }
321 43668 : if (m.LeftEqualsRight()) return ReplaceBool(true); // x <= x => true
322 43662 : 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 146286 : Float64BinopMatcher m(node);
362 146293 : if (m.IsFoldable()) { // K + K => K
363 23834 : return ReplaceFloat64(m.left().Value() + m.right().Value());
364 : }
365 134376 : break;
366 : }
367 : case IrOpcode::kFloat64Sub: {
368 37225 : Float64BinopMatcher m(node);
369 75042 : if (allow_signalling_nan_ && m.right().Is(0) &&
370 592 : (Double(m.right().Value()).Sign() > 0)) {
371 22334 : return Replace(m.left().node()); // x - 0 => x
372 : }
373 36886 : if (m.right().IsNaN()) { // x - NaN => NaN
374 : // Do some calculation to make a signalling NaN quiet.
375 538 : return ReplaceFloat64(m.right().Value() - m.right().Value());
376 : }
377 36348 : if (m.left().IsNaN()) { // NaN - x => NaN
378 : // Do some calculation to make a signalling NaN quiet.
379 509 : return ReplaceFloat64(m.left().Value() - m.left().Value());
380 : }
381 35839 : if (m.IsFoldable()) { // L - R => (L - R)
382 11626 : return ReplaceFloat64(m.left().Value() - m.right().Value());
383 : }
384 24213 : if (allow_signalling_nan_ && m.left().IsMinusZero()) {
385 : // -0.0 - round_down(-0.0 - R) => round_up(R)
386 18642 : 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 9322 : node->RemoveInput(0);
398 9322 : NodeProperties::ChangeOp(node, machine()->Float64Neg());
399 : return Changed(node);
400 : }
401 14891 : break;
402 : }
403 : case IrOpcode::kFloat64Mul: {
404 24507 : Float64BinopMatcher m(node);
405 49014 : if (allow_signalling_nan_ && m.right().Is(1))
406 11387 : return Replace(m.left().node()); // x * 1.0 => x
407 24453 : if (m.right().Is(-1)) { // x * -1.0 => -0.0 - x
408 9529 : node->ReplaceInput(0, Float64Constant(-0.0));
409 9529 : node->ReplaceInput(1, m.left().node());
410 9529 : NodeProperties::ChangeOp(node, machine()->Float64Sub());
411 : return Changed(node);
412 : }
413 14924 : if (m.right().IsNaN()) { // x * NaN => NaN
414 : // Do some calculation to make a signalling NaN quiet.
415 34 : return ReplaceFloat64(m.right().Value() - m.right().Value());
416 : }
417 14890 : if (m.IsFoldable()) { // K * K => K
418 1635 : return ReplaceFloat64(m.left().Value() * m.right().Value());
419 : }
420 13255 : 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 13120 : break;
426 : }
427 : case IrOpcode::kFloat64Div: {
428 29738 : Float64BinopMatcher m(node);
429 59476 : if (allow_signalling_nan_ && m.right().Is(1))
430 5878 : 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 29628 : if (m.right().IsNaN()) { // x / NaN => NaN
433 : // Do some calculation to make a signalling NaN quiet.
434 30 : return ReplaceFloat64(m.right().Value() - m.right().Value());
435 : }
436 29598 : if (m.left().IsNaN()) { // NaN / x => NaN
437 : // Do some calculation to make a signalling NaN quiet.
438 46 : return ReplaceFloat64(m.left().Value() - m.left().Value());
439 : }
440 29552 : if (m.IsFoldable()) { // K / K => K
441 : return ReplaceFloat64(
442 2789 : base::Divide(m.left().Value(), m.right().Value()));
443 : }
444 53526 : if (allow_signalling_nan_ && m.right().Is(-1)) { // x / -1.0 => -x
445 64 : node->RemoveInput(1);
446 64 : NodeProperties::ChangeOp(node, machine()->Float64Neg());
447 : return Changed(node);
448 : }
449 26699 : 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 5678 : node->ReplaceInput(1, Float64Constant(1.0 / m.right().Value()));
454 2839 : NodeProperties::ChangeOp(node, machine()->Float64Mul());
455 : return Changed(node);
456 : }
457 23860 : break;
458 : }
459 : case IrOpcode::kFloat64Mod: {
460 3183 : Float64BinopMatcher m(node);
461 3183 : if (m.right().Is(0)) { // x % 0 => NaN
462 1242 : return ReplaceFloat64(std::numeric_limits<double>::quiet_NaN());
463 : }
464 3032 : if (m.right().IsNaN()) { // x % NaN => NaN
465 : return Replace(m.right().node());
466 : }
467 2995 : if (m.left().IsNaN()) { // NaN % x => NaN
468 : return Replace(m.left().node());
469 : }
470 2968 : if (m.IsFoldable()) { // K % K => K
471 1027 : return ReplaceFloat64(Modulo(m.left().Value(), m.right().Value()));
472 : }
473 1941 : 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 10067 : Float64BinopMatcher m(node);
507 10067 : if (m.right().IsNaN()) {
508 10006 : return Replace(m.right().node());
509 : }
510 10066 : if (m.left().IsNaN()) {
511 : return Replace(m.left().node());
512 : }
513 10065 : if (m.IsFoldable()) {
514 : return ReplaceFloat64(
515 10004 : base::ieee754::atan2(m.left().Value(), m.right().Value()));
516 : }
517 61 : 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 321 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::cos(m.Value()));
527 : break;
528 : }
529 : case IrOpcode::kFloat64Cosh: {
530 : Float64Matcher m(node->InputAt(0));
531 170 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::cosh(m.Value()));
532 : break;
533 : }
534 : case IrOpcode::kFloat64Exp: {
535 : Float64Matcher m(node->InputAt(0));
536 224 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::exp(m.Value()));
537 : break;
538 : }
539 : case IrOpcode::kFloat64Expm1: {
540 : Float64Matcher m(node->InputAt(0));
541 77 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::expm1(m.Value()));
542 : break;
543 : }
544 : case IrOpcode::kFloat64Log: {
545 : Float64Matcher m(node->InputAt(0));
546 483 : 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 11143 : Float64BinopMatcher m(node);
566 11143 : if (m.IsFoldable()) {
567 : return ReplaceFloat64(
568 21544 : base::ieee754::pow(m.left().Value(), m.right().Value()));
569 372 : } else if (m.right().Is(0.0)) { // x ** +-0.0 => 1.0
570 : return ReplaceFloat64(1.0);
571 370 : } 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 370 : } 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 370 : } 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 370 : } 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 370 : break;
591 : }
592 : case IrOpcode::kFloat64Sin: {
593 : Float64Matcher m(node->InputAt(0));
594 337 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::sin(m.Value()));
595 : break;
596 : }
597 : case IrOpcode::kFloat64Sinh: {
598 : Float64Matcher m(node->InputAt(0));
599 170 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::sinh(m.Value()));
600 : break;
601 : }
602 : case IrOpcode::kFloat64Tan: {
603 : Float64Matcher m(node->InputAt(0));
604 218 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::tan(m.Value()));
605 : break;
606 : }
607 : case IrOpcode::kFloat64Tanh: {
608 : Float64Matcher m(node->InputAt(0));
609 170 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::tanh(m.Value()));
610 : break;
611 : }
612 : case IrOpcode::kChangeFloat32ToFloat64: {
613 : Float32Matcher m(node->InputAt(0));
614 12141 : if (m.HasValue()) {
615 139 : 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 139 : return ReplaceFloat64(m.Value());
620 : }
621 : break;
622 : }
623 : case IrOpcode::kChangeFloat64ToInt32: {
624 : Float64Matcher m(node->InputAt(0));
625 2999 : if (m.HasValue()) return ReplaceInt32(FastD2IChecked(m.Value()));
626 2857 : if (m.IsChangeInt32ToFloat64()) return Replace(m.node()->InputAt(0));
627 : break;
628 : }
629 : case IrOpcode::kChangeFloat64ToInt64: {
630 : Float64Matcher m(node->InputAt(0));
631 143 : if (m.HasValue()) return ReplaceInt64(static_cast<int64_t>(m.Value()));
632 39 : if (m.IsChangeInt64ToFloat64()) return Replace(m.node()->InputAt(0));
633 : break;
634 : }
635 : case IrOpcode::kChangeFloat64ToUint32: {
636 : Float64Matcher m(node->InputAt(0));
637 719 : if (m.HasValue()) return ReplaceInt32(FastD2UI(m.Value()));
638 605 : if (m.IsChangeUint32ToFloat64()) return Replace(m.node()->InputAt(0));
639 : break;
640 : }
641 : case IrOpcode::kChangeInt32ToFloat64: {
642 : Int32Matcher m(node->InputAt(0));
643 274554 : if (m.HasValue()) return ReplaceFloat64(FastI2D(m.Value()));
644 : break;
645 : }
646 : case IrOpcode::kChangeInt32ToInt64: {
647 : Int32Matcher m(node->InputAt(0));
648 272805 : if (m.HasValue()) return ReplaceInt64(m.Value());
649 : break;
650 : }
651 : case IrOpcode::kChangeInt64ToFloat64: {
652 : Int64Matcher m(node->InputAt(0));
653 925 : if (m.HasValue()) return ReplaceFloat64(static_cast<double>(m.Value()));
654 369 : if (m.IsChangeFloat64ToInt64()) return Replace(m.node()->InputAt(0));
655 : break;
656 : }
657 : case IrOpcode::kChangeUint32ToFloat64: {
658 : Uint32Matcher m(node->InputAt(0));
659 6675 : if (m.HasValue()) return ReplaceFloat64(FastUI2D(m.Value()));
660 : break;
661 : }
662 : case IrOpcode::kChangeUint32ToUint64: {
663 : Uint32Matcher m(node->InputAt(0));
664 286483 : 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 26997 : if (m.HasValue()) return ReplaceInt32(DoubleToInt32(m.Value()));
670 23710 : if (m.IsChangeInt32ToFloat64()) return Replace(m.node()->InputAt(0));
671 : return NoChange();
672 : }
673 : case IrOpcode::kTruncateInt64ToInt32: {
674 : Int64Matcher m(node->InputAt(0));
675 537617 : if (m.HasValue()) return ReplaceInt32(static_cast<int32_t>(m.Value()));
676 446216 : if (m.IsChangeInt32ToInt64()) return Replace(m.node()->InputAt(0));
677 : break;
678 : }
679 : case IrOpcode::kTruncateFloat64ToFloat32: {
680 : Float64Matcher m(node->InputAt(0));
681 8162 : if (m.HasValue()) {
682 673 : 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 7489 : 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 73037 : if (m.HasValue()) {
695 290 : return ReplaceInt32(DoubleToInt32(m.Value()));
696 : }
697 72747 : 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 3331026 : return ReduceStore(node);
707 : case IrOpcode::kFloat64Equal:
708 : case IrOpcode::kFloat64LessThan:
709 : case IrOpcode::kFloat64LessThanOrEqual:
710 228559 : return ReduceFloat64Compare(node);
711 : case IrOpcode::kFloat64RoundDown:
712 55538 : return ReduceFloat64RoundDown(node);
713 : case IrOpcode::kBitcastTaggedToWord: {
714 : NodeMatcher m(node->InputAt(0));
715 1316399 : 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 550801 : Reduction MachineOperatorReducer::ReduceInt32Add(Node* node) {
728 : DCHECK_EQ(IrOpcode::kInt32Add, node->opcode());
729 550801 : Int32BinopMatcher m(node);
730 550806 : if (m.right().Is(0)) return Replace(m.left().node()); // x + 0 => x
731 526787 : if (m.IsFoldable()) { // K + K => K
732 : return ReplaceInt32(
733 38632 : base::AddWithWraparound(m.left().Value(), m.right().Value()));
734 : }
735 488155 : if (m.left().IsInt32Sub()) {
736 1889 : Int32BinopMatcher mleft(m.left().node());
737 1889 : 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 488033 : if (m.right().IsInt32Sub()) {
746 621 : Int32BinopMatcher mright(m.right().node());
747 621 : 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 1965933 : Reduction MachineOperatorReducer::ReduceInt64Add(Node* node) {
758 : DCHECK_EQ(IrOpcode::kInt64Add, node->opcode());
759 1965933 : Int64BinopMatcher m(node);
760 1965934 : if (m.right().Is(0)) return Replace(m.left().node()); // x + 0 => 0
761 1953191 : if (m.IsFoldable()) {
762 : return ReplaceInt64(
763 77059 : base::AddWithWraparound(m.left().Value(), m.right().Value()));
764 : }
765 : return NoChange();
766 : }
767 :
768 70155 : Reduction MachineOperatorReducer::ReduceInt32Sub(Node* node) {
769 : DCHECK_EQ(IrOpcode::kInt32Sub, node->opcode());
770 70155 : Int32BinopMatcher m(node);
771 70155 : if (m.right().Is(0)) return Replace(m.left().node()); // x - 0 => x
772 69474 : if (m.IsFoldable()) { // K - K => K
773 : return ReplaceInt32(
774 19551 : base::SubWithWraparound(m.left().Value(), m.right().Value()));
775 : }
776 49923 : if (m.LeftEqualsRight()) return ReplaceInt32(0); // x - x => 0
777 49923 : if (m.right().HasValue()) { // x - K => x + -K
778 22703 : node->ReplaceInput(
779 22703 : 1, Int32Constant(base::NegateWithWraparound(m.right().Value())));
780 22703 : NodeProperties::ChangeOp(node, machine()->Int32Add());
781 22703 : Reduction const reduction = ReduceInt32Add(node);
782 22703 : return reduction.Changed() ? reduction : Changed(node);
783 : }
784 : return NoChange();
785 : }
786 :
787 329678 : Reduction MachineOperatorReducer::ReduceInt64Sub(Node* node) {
788 : DCHECK_EQ(IrOpcode::kInt64Sub, node->opcode());
789 329678 : Int64BinopMatcher m(node);
790 329677 : if (m.right().Is(0)) return Replace(m.left().node()); // x - 0 => x
791 323162 : if (m.IsFoldable()) { // K - K => K
792 : return ReplaceInt64(
793 35345 : base::SubWithWraparound(m.left().Value(), m.right().Value()));
794 : }
795 287817 : if (m.LeftEqualsRight()) return Replace(Int64Constant(0)); // x - x => 0
796 287809 : if (m.right().HasValue()) { // x - K => x + -K
797 552920 : node->ReplaceInput(
798 276461 : 1, Int64Constant(base::NegateWithWraparound(m.right().Value())));
799 276461 : NodeProperties::ChangeOp(node, machine()->Int64Add());
800 276461 : Reduction const reduction = ReduceInt64Add(node);
801 276461 : return reduction.Changed() ? reduction : Changed(node);
802 : }
803 : return NoChange();
804 : }
805 :
806 20264 : Reduction MachineOperatorReducer::ReduceInt32Div(Node* node) {
807 20264 : Int32BinopMatcher m(node);
808 20264 : if (m.left().Is(0)) return Replace(m.left().node()); // 0 / x => 0
809 19973 : if (m.right().Is(0)) return Replace(m.right().node()); // x / 0 => 0
810 19972 : if (m.right().Is(1)) return Replace(m.left().node()); // x / 1 => x
811 19652 : if (m.IsFoldable()) { // K / K => K
812 : return ReplaceInt32(
813 16014 : base::bits::SignedDiv32(m.left().Value(), m.right().Value()));
814 : }
815 3638 : if (m.LeftEqualsRight()) { // x / x => x != 0
816 : Node* const zero = Int32Constant(0);
817 5 : return Replace(Word32Equal(Word32Equal(m.left().node(), zero), zero));
818 : }
819 3633 : if (m.right().Is(-1)) { // x / -1 => 0 - x
820 25 : node->ReplaceInput(0, Int32Constant(0));
821 25 : node->ReplaceInput(1, m.left().node());
822 25 : node->TrimInputCount(2);
823 25 : NodeProperties::ChangeOp(node, machine()->Int32Sub());
824 : return Changed(node);
825 : }
826 3608 : if (m.right().HasValue()) {
827 2825 : int32_t const divisor = m.right().Value();
828 : Node* const dividend = m.left().node();
829 : Node* quotient = dividend;
830 2825 : if (base::bits::IsPowerOfTwo(Abs(divisor))) {
831 746 : uint32_t const shift = WhichPowerOf2(Abs(divisor));
832 : DCHECK_NE(0u, shift);
833 746 : if (shift > 1) {
834 638 : quotient = Word32Sar(quotient, 31);
835 : }
836 746 : quotient = Int32Add(Word32Shr(quotient, 32u - shift), dividend);
837 746 : quotient = Word32Sar(quotient, shift);
838 : } else {
839 2079 : quotient = Int32Div(quotient, Abs(divisor));
840 : }
841 2825 : if (divisor < 0) {
842 1284 : node->ReplaceInput(0, Int32Constant(0));
843 1284 : node->ReplaceInput(1, quotient);
844 1284 : node->TrimInputCount(2);
845 1284 : NodeProperties::ChangeOp(node, machine()->Int32Sub());
846 : return Changed(node);
847 : }
848 : return Replace(quotient);
849 : }
850 : return NoChange();
851 : }
852 :
853 :
854 19316 : Reduction MachineOperatorReducer::ReduceUint32Div(Node* node) {
855 19316 : Uint32BinopMatcher m(node);
856 19316 : if (m.left().Is(0)) return Replace(m.left().node()); // 0 / x => 0
857 18968 : if (m.right().Is(0)) return Replace(m.right().node()); // x / 0 => 0
858 18920 : if (m.right().Is(1)) return Replace(m.left().node()); // x / 1 => x
859 18577 : if (m.IsFoldable()) { // K / K => K
860 : return ReplaceUint32(
861 18154 : base::bits::UnsignedDiv32(m.left().Value(), m.right().Value()));
862 : }
863 423 : 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 422 : 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 30610 : Reduction MachineOperatorReducer::ReduceInt32Mod(Node* node) {
884 30610 : Int32BinopMatcher m(node);
885 30610 : if (m.left().Is(0)) return Replace(m.left().node()); // 0 % x => 0
886 30206 : if (m.right().Is(0)) return Replace(m.right().node()); // x % 0 => 0
887 30106 : if (m.right().Is(1)) return ReplaceInt32(0); // x % 1 => 0
888 29794 : if (m.right().Is(-1)) return ReplaceInt32(0); // x % -1 => 0
889 29508 : if (m.LeftEqualsRight()) return ReplaceInt32(0); // x % x => 0
890 29499 : if (m.IsFoldable()) { // K % K => K
891 : return ReplaceInt32(
892 25563 : base::bits::SignedMod32(m.left().Value(), m.right().Value()));
893 : }
894 3936 : if (m.right().HasValue()) {
895 : Node* const dividend = m.left().node();
896 2847 : uint32_t const divisor = Abs(m.right().Value());
897 2847 : if (base::bits::IsPowerOfTwo(divisor)) {
898 760 : 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 1520 : BranchHint::kFalse);
903 : return Replace(
904 : d.Phi(MachineRepresentation::kWord32,
905 : Int32Sub(zero, Word32And(Int32Sub(zero, dividend), mask)),
906 760 : Word32And(dividend, mask)));
907 : } else {
908 2087 : Node* quotient = Int32Div(dividend, divisor);
909 : DCHECK_EQ(dividend, node->InputAt(0));
910 2087 : node->ReplaceInput(1, Int32Mul(quotient, Int32Constant(divisor)));
911 2087 : node->TrimInputCount(2);
912 2087 : NodeProperties::ChangeOp(node, machine()->Int32Sub());
913 : }
914 : return Changed(node);
915 : }
916 : return NoChange();
917 : }
918 :
919 :
920 21244 : Reduction MachineOperatorReducer::ReduceUint32Mod(Node* node) {
921 21244 : Uint32BinopMatcher m(node);
922 21244 : if (m.left().Is(0)) return Replace(m.left().node()); // 0 % x => 0
923 20853 : if (m.right().Is(0)) return Replace(m.right().node()); // x % 0 => 0
924 20805 : if (m.right().Is(1)) return ReplaceUint32(0); // x % 1 => 0
925 20462 : if (m.LeftEqualsRight()) return ReplaceInt32(0); // x % x => 0
926 20460 : if (m.IsFoldable()) { // K % K => K
927 : return ReplaceUint32(
928 18200 : base::bits::UnsignedMod32(m.left().Value(), m.right().Value()));
929 : }
930 2260 : if (m.right().HasValue()) {
931 : Node* const dividend = m.left().node();
932 1871 : uint32_t const divisor = m.right().Value();
933 1871 : if (base::bits::IsPowerOfTwo(divisor)) { // x % 2^n => x & 2^n-1
934 1078 : node->ReplaceInput(1, Uint32Constant(m.right().Value() - 1));
935 539 : node->TrimInputCount(2);
936 539 : NodeProperties::ChangeOp(node, machine()->Word32And());
937 : } else {
938 1332 : Node* quotient = Uint32Div(dividend, divisor);
939 : DCHECK_EQ(dividend, node->InputAt(0));
940 1332 : node->ReplaceInput(1, Int32Mul(quotient, Uint32Constant(divisor)));
941 1332 : node->TrimInputCount(2);
942 1332 : NodeProperties::ChangeOp(node, machine()->Int32Sub());
943 : }
944 : return Changed(node);
945 : }
946 : return NoChange();
947 : }
948 :
949 :
950 3331026 : Reduction MachineOperatorReducer::ReduceStore(Node* node) {
951 : NodeMatcher nm(node);
952 : MachineRepresentation rep;
953 : int value_input;
954 3331026 : if (nm.IsStore()) {
955 3331026 : 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 3331027 : switch (value->opcode()) {
966 : case IrOpcode::kWord32And: {
967 7330 : Uint32BinopMatcher m(value);
968 19941 : if (m.right().HasValue() && ((rep == MachineRepresentation::kWord8 &&
969 7123 : (m.right().Value() & 0xFF) == 0xFF) ||
970 1313 : (rep == MachineRepresentation::kWord16 &&
971 1313 : (m.right().Value() & 0xFFFF) == 0xFFFF))) {
972 6358 : node->ReplaceInput(value_input, m.left().node());
973 6358 : return Changed(node);
974 : }
975 972 : break;
976 : }
977 : case IrOpcode::kWord32Sar: {
978 1010 : Int32BinopMatcher m(value);
979 2149 : 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 688 : break;
990 : }
991 : default:
992 : break;
993 : }
994 : return NoChange();
995 : }
996 :
997 :
998 442054 : Reduction MachineOperatorReducer::ReduceProjection(size_t index, Node* node) {
999 442054 : switch (node->opcode()) {
1000 : case IrOpcode::kInt32AddWithOverflow: {
1001 : DCHECK(index == 0 || index == 1);
1002 363973 : Int32BinopMatcher m(node);
1003 363978 : if (m.IsFoldable()) {
1004 : int32_t val;
1005 20752 : bool ovf = base::bits::SignedAddOverflow32(m.left().Value(),
1006 : m.right().Value(), &val);
1007 20752 : return ReplaceInt32(index == 0 ? val : ovf);
1008 : }
1009 343226 : if (m.right().Is(0)) {
1010 32 : return Replace(index == 0 ? m.left().node() : m.right().node());
1011 : }
1012 343194 : break;
1013 : }
1014 : case IrOpcode::kInt32SubWithOverflow: {
1015 : DCHECK(index == 0 || index == 1);
1016 41827 : Int32BinopMatcher m(node);
1017 41827 : 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 21771 : if (m.right().Is(0)) {
1024 2 : return Replace(index == 0 ? m.left().node() : m.right().node());
1025 : }
1026 21769 : break;
1027 : }
1028 : case IrOpcode::kInt32MulWithOverflow: {
1029 : DCHECK(index == 0 || index == 1);
1030 26953 : Int32BinopMatcher m(node);
1031 26953 : 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 6643 : if (m.right().Is(0)) {
1038 : return Replace(m.right().node());
1039 : }
1040 6557 : if (m.right().Is(1)) {
1041 72 : return index == 0 ? Replace(m.left().node()) : ReplaceInt32(0);
1042 : }
1043 6485 : break;
1044 : }
1045 : default:
1046 : break;
1047 : }
1048 : return NoChange();
1049 : }
1050 :
1051 :
1052 281048 : Reduction MachineOperatorReducer::ReduceWord32Shifts(Node* node) {
1053 : DCHECK((node->opcode() == IrOpcode::kWord32Shl) ||
1054 : (node->opcode() == IrOpcode::kWord32Shr) ||
1055 : (node->opcode() == IrOpcode::kWord32Sar));
1056 281048 : 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 280733 : Int32BinopMatcher m(node);
1060 280733 : if (m.right().IsWord32And()) {
1061 2056 : Int32BinopMatcher mright(m.right().node());
1062 2056 : if (mright.right().Is(0x1F)) {
1063 1057 : node->ReplaceInput(1, mright.left().node());
1064 1057 : return Changed(node);
1065 : }
1066 : }
1067 : }
1068 : return NoChange();
1069 : }
1070 :
1071 :
1072 71342 : Reduction MachineOperatorReducer::ReduceWord32Shl(Node* node) {
1073 : DCHECK_EQ(IrOpcode::kWord32Shl, node->opcode());
1074 71342 : Int32BinopMatcher m(node);
1075 71342 : if (m.right().Is(0)) return Replace(m.left().node()); // x << 0 => x
1076 70616 : if (m.IsFoldable()) { // K << K => K
1077 : return ReplaceInt32(
1078 13901 : base::ShlWithWraparound(m.left().Value(), m.right().Value()));
1079 : }
1080 56715 : if (m.right().IsInRange(1, 31)) {
1081 : // (x >>> K) << K => x & ~(2^K - 1)
1082 : // (x >> K) << K => x & ~(2^K - 1)
1083 53309 : if (m.left().IsWord32Sar() || m.left().IsWord32Shr()) {
1084 7218 : Int32BinopMatcher mleft(m.left().node());
1085 7218 : if (mleft.right().Is(m.right().Value())) {
1086 5802 : node->ReplaceInput(0, mleft.left().node());
1087 5802 : node->ReplaceInput(1,
1088 11604 : Uint32Constant(~((1U << m.right().Value()) - 1U)));
1089 5802 : NodeProperties::ChangeOp(node, machine()->Word32And());
1090 5802 : Reduction reduction = ReduceWord32And(node);
1091 5802 : return reduction.Changed() ? reduction : Changed(node);
1092 : }
1093 : }
1094 : }
1095 50913 : return ReduceWord32Shifts(node);
1096 : }
1097 :
1098 553599 : Reduction MachineOperatorReducer::ReduceWord64Shl(Node* node) {
1099 : DCHECK_EQ(IrOpcode::kWord64Shl, node->opcode());
1100 553599 : Int64BinopMatcher m(node);
1101 553599 : if (m.right().Is(0)) return Replace(m.left().node()); // x << 0 => x
1102 553189 : if (m.IsFoldable()) { // K << K => K
1103 : return ReplaceInt64(
1104 88281 : base::ShlWithWraparound(m.left().Value(), m.right().Value()));
1105 : }
1106 : return NoChange();
1107 : }
1108 :
1109 76143 : Reduction MachineOperatorReducer::ReduceWord32Shr(Node* node) {
1110 76143 : Uint32BinopMatcher m(node);
1111 76143 : if (m.right().Is(0)) return Replace(m.left().node()); // x >>> 0 => x
1112 63156 : if (m.IsFoldable()) { // K >>> K => K
1113 9993 : return ReplaceInt32(m.left().Value() >> (m.right().Value() & 31));
1114 : }
1115 53163 : if (m.left().IsWord32And() && m.right().HasValue()) {
1116 24146 : Uint32BinopMatcher mleft(m.left().node());
1117 24146 : if (mleft.right().HasValue()) {
1118 24143 : uint32_t shift = m.right().Value() & 31;
1119 24143 : uint32_t mask = mleft.right().Value();
1120 24143 : if ((mask >> shift) == 0) {
1121 : // (m >>> s) == 0 implies ((x & m) >>> s) == 0
1122 31 : return ReplaceInt32(0);
1123 : }
1124 : }
1125 : }
1126 53132 : return ReduceWord32Shifts(node);
1127 : }
1128 :
1129 49826 : Reduction MachineOperatorReducer::ReduceWord64Shr(Node* node) {
1130 : DCHECK_EQ(IrOpcode::kWord64Shr, node->opcode());
1131 49826 : Uint64BinopMatcher m(node);
1132 49826 : if (m.right().Is(0)) return Replace(m.left().node()); // x >>> 0 => x
1133 49416 : if (m.IsFoldable()) { // K >> K => K
1134 25515 : return ReplaceInt64(m.left().Value() >> (m.right().Value() & 63));
1135 : }
1136 : return NoChange();
1137 : }
1138 :
1139 188115 : Reduction MachineOperatorReducer::ReduceWord32Sar(Node* node) {
1140 188115 : Int32BinopMatcher m(node);
1141 188115 : if (m.right().Is(0)) return Replace(m.left().node()); // x >> 0 => x
1142 187311 : if (m.IsFoldable()) { // K >> K => K
1143 10257 : return ReplaceInt32(m.left().Value() >> (m.right().Value() & 31));
1144 : }
1145 177054 : if (m.left().IsWord32Shl()) {
1146 1263 : Int32BinopMatcher mleft(m.left().node());
1147 1263 : 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 1214 : } 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 177003 : return ReduceWord32Shifts(node);
1172 : }
1173 :
1174 253821 : Reduction MachineOperatorReducer::ReduceWord64Sar(Node* node) {
1175 253821 : Int64BinopMatcher m(node);
1176 253821 : if (m.right().Is(0)) return Replace(m.left().node()); // x >> 0 => x
1177 253411 : if (m.IsFoldable()) {
1178 32859 : return ReplaceInt64(m.left().Value() >> (m.right().Value() & 63));
1179 : }
1180 : return NoChange();
1181 : }
1182 :
1183 624615 : Reduction MachineOperatorReducer::ReduceWord32And(Node* node) {
1184 : DCHECK_EQ(IrOpcode::kWord32And, node->opcode());
1185 624615 : Int32BinopMatcher m(node);
1186 624615 : if (m.right().Is(0)) return Replace(m.right().node()); // x & 0 => 0
1187 622712 : if (m.right().Is(-1)) return Replace(m.left().node()); // x & -1 => x
1188 623398 : if (m.left().IsComparison() && m.right().Is(1)) { // CMP & 1 => CMP
1189 : return Replace(m.left().node());
1190 : }
1191 622053 : if (m.IsFoldable()) { // K & K => K
1192 27951 : return ReplaceInt32(m.left().Value() & m.right().Value());
1193 : }
1194 594102 : if (m.LeftEqualsRight()) return Replace(m.left().node()); // x & x => x
1195 594001 : if (m.left().IsWord32And() && m.right().HasValue()) {
1196 21587 : Int32BinopMatcher mleft(m.left().node());
1197 21587 : if (mleft.right().HasValue()) { // (x & K) & K => x & K
1198 19719 : node->ReplaceInput(0, mleft.left().node());
1199 19719 : node->ReplaceInput(
1200 19719 : 1, Int32Constant(m.right().Value() & mleft.right().Value()));
1201 19719 : Reduction const reduction = ReduceWord32And(node);
1202 19719 : return reduction.Changed() ? reduction : Changed(node);
1203 : }
1204 : }
1205 574282 : if (m.right().IsNegativePowerOf2()) {
1206 258146 : int32_t const mask = m.right().Value();
1207 : int32_t const neg_mask = base::NegateWithWraparound(mask);
1208 258146 : 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 256004 : } else if (m.left().IsInt32Add()) {
1217 94794 : Int32BinopMatcher mleft(m.left().node());
1218 169523 : if (mleft.right().HasValue() &&
1219 74729 : (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 20212 : 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 17289 : 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 10146 : 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 10115 : 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 161210 : } else if (m.left().IsInt32Mul()) {
1276 5902 : Int32BinopMatcher mleft(m.left().node());
1277 5902 : 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 82101 : Reduction MachineOperatorReducer::TryMatchWord32Ror(Node* node) {
1287 : DCHECK(IrOpcode::kWord32Or == node->opcode() ||
1288 : IrOpcode::kWord32Xor == node->opcode());
1289 82101 : 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 87654 : if (m.left().IsWord32Shl() && m.right().IsWord32Shr()) {
1299 : shl = m.left().node();
1300 : shr = m.right().node();
1301 81588 : } 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 915 : Int32BinopMatcher mshl(shl);
1309 915 : Int32BinopMatcher mshr(shr);
1310 915 : if (mshl.left().node() != mshr.left().node()) return NoChange();
1311 :
1312 621 : 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 239 : if (mshl.right().IsInt32Sub()) {
1319 : sub = mshl.right().node();
1320 : y = mshr.right().node();
1321 203 : } else if (mshr.right().IsInt32Sub()) {
1322 : sub = mshr.right().node();
1323 : y = mshl.right().node();
1324 : } else {
1325 202 : return NoChange();
1326 : }
1327 :
1328 155 : Int32BinopMatcher msub(sub);
1329 310 : if (!msub.left().Is(32) || msub.right().node() != y) return NoChange();
1330 : }
1331 :
1332 419 : node->ReplaceInput(0, mshl.left().node());
1333 419 : node->ReplaceInput(1, mshr.right().node());
1334 419 : NodeProperties::ChangeOp(node, machine()->Word32Ror());
1335 : return Changed(node);
1336 : }
1337 :
1338 112400 : Reduction MachineOperatorReducer::ReduceWord32Or(Node* node) {
1339 : DCHECK_EQ(IrOpcode::kWord32Or, node->opcode());
1340 112400 : Int32BinopMatcher m(node);
1341 112400 : if (m.right().Is(0)) return Replace(m.left().node()); // x | 0 => x
1342 97128 : if (m.right().Is(-1)) return Replace(m.right().node()); // x | -1 => -1
1343 94579 : if (m.IsFoldable()) { // K | K => K
1344 18477 : return ReplaceInt32(m.left().Value() | m.right().Value());
1345 : }
1346 76102 : if (m.LeftEqualsRight()) return Replace(m.left().node()); // x | x => x
1347 :
1348 76053 : return TryMatchWord32Ror(node);
1349 : }
1350 :
1351 24267 : Reduction MachineOperatorReducer::ReduceWord32Xor(Node* node) {
1352 : DCHECK_EQ(IrOpcode::kWord32Xor, node->opcode());
1353 24267 : Int32BinopMatcher m(node);
1354 24267 : if (m.right().Is(0)) return Replace(m.left().node()); // x ^ 0 => x
1355 23710 : if (m.IsFoldable()) { // K ^ K => K
1356 17628 : return ReplaceInt32(m.left().Value() ^ m.right().Value());
1357 : }
1358 6082 : if (m.LeftEqualsRight()) return ReplaceInt32(0); // x ^ x => 0
1359 6287 : 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 6048 : 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 195846 : if (m.HasValue()) {
1399 55126 : double v = m.Value();
1400 55126 : return DoubleToFloat32(v) == v;
1401 : }
1402 : return false;
1403 : }
1404 :
1405 : } // namespace
1406 :
1407 :
1408 228556 : Reduction MachineOperatorReducer::ReduceFloat64Compare(Node* node) {
1409 : DCHECK(IrOpcode::kFloat64Equal == node->opcode() ||
1410 : IrOpcode::kFloat64LessThan == node->opcode() ||
1411 : IrOpcode::kFloat64LessThanOrEqual == node->opcode());
1412 228556 : Float64BinopMatcher m(node);
1413 228557 : if (m.IsFoldable()) {
1414 32609 : switch (node->opcode()) {
1415 : case IrOpcode::kFloat64Equal:
1416 11787 : return ReplaceBool(m.left().Value() == m.right().Value());
1417 : case IrOpcode::kFloat64LessThan:
1418 10695 : 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 197274 : } else if ((m.left().IsChangeFloat32ToFloat64() &&
1425 195420 : m.right().IsChangeFloat32ToFloat64()) ||
1426 799 : (m.left().IsChangeFloat32ToFloat64() &&
1427 390995 : IsFloat64RepresentableAsFloat32(m.right())) ||
1428 54661 : (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 1141 : switch (node->opcode()) {
1436 : case IrOpcode::kFloat64Equal:
1437 289 : NodeProperties::ChangeOp(node, machine()->Float32Equal());
1438 289 : break;
1439 : case IrOpcode::kFloat64LessThan:
1440 576 : NodeProperties::ChangeOp(node, machine()->Float32LessThan());
1441 576 : break;
1442 : case IrOpcode::kFloat64LessThanOrEqual:
1443 276 : NodeProperties::ChangeOp(node, machine()->Float32LessThanOrEqual());
1444 276 : break;
1445 : default:
1446 0 : UNREACHABLE();
1447 : }
1448 1381 : node->ReplaceInput(
1449 : 0, m.left().HasValue()
1450 240 : ? Float32Constant(static_cast<float>(m.left().Value()))
1451 1141 : : m.left().InputAt(0));
1452 1515 : node->ReplaceInput(
1453 : 1, m.right().HasValue()
1454 374 : ? Float32Constant(static_cast<float>(m.right().Value()))
1455 1141 : : m.right().InputAt(0));
1456 : return Changed(node);
1457 : }
1458 : return NoChange();
1459 : }
1460 :
1461 55538 : Reduction MachineOperatorReducer::ReduceFloat64RoundDown(Node* node) {
1462 : DCHECK_EQ(IrOpcode::kFloat64RoundDown, node->opcode());
1463 : Float64Matcher m(node->InputAt(0));
1464 55538 : if (m.HasValue()) {
1465 331 : 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 120216 : } // namespace v8
|