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 2150104 : MachineOperatorReducer::MachineOperatorReducer(Editor* editor,
24 : MachineGraph* mcgraph,
25 : bool allow_signalling_nan)
26 : : AdvancedReducer(editor),
27 : mcgraph_(mcgraph),
28 2150104 : allow_signalling_nan_(allow_signalling_nan) {}
29 :
30 : MachineOperatorReducer::~MachineOperatorReducer() = default;
31 :
32 :
33 66860 : Node* MachineOperatorReducer::Float32Constant(volatile float value) {
34 133720 : return graph()->NewNode(common()->Float32Constant(value));
35 : }
36 :
37 :
38 0 : Node* MachineOperatorReducer::Float64Constant(volatile double value) {
39 87566 : return mcgraph()->Float64Constant(value);
40 : }
41 :
42 :
43 0 : Node* MachineOperatorReducer::Int32Constant(int32_t value) {
44 533444 : return mcgraph()->Int32Constant(value);
45 : }
46 :
47 :
48 546835 : Node* MachineOperatorReducer::Int64Constant(int64_t value) {
49 1093670 : 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 88604 : Node* MachineOperatorReducer::Word32And(Node* lhs, Node* rhs) {
68 88604 : Node* const node = graph()->NewNode(machine()->Word32And(), lhs, rhs);
69 88604 : Reduction const reduction = ReduceWord32And(node);
70 88604 : return reduction.Changed() ? reduction.replacement() : node;
71 : }
72 :
73 :
74 5526 : Node* MachineOperatorReducer::Word32Sar(Node* lhs, uint32_t rhs) {
75 5526 : if (rhs == 0) return lhs;
76 10730 : return graph()->NewNode(machine()->Word32Sar(), lhs, Uint32Constant(rhs));
77 : }
78 :
79 :
80 7761 : Node* MachineOperatorReducer::Word32Shr(Node* lhs, uint32_t rhs) {
81 7761 : if (rhs == 0) return lhs;
82 13348 : 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 6192 : Node* MachineOperatorReducer::Int32Add(Node* lhs, Node* rhs) {
92 6192 : Node* const node = graph()->NewNode(machine()->Int32Add(), lhs, rhs);
93 6192 : Reduction const reduction = ReduceInt32Add(node);
94 6192 : return reduction.Changed() ? reduction.replacement() : node;
95 : }
96 :
97 :
98 1524 : Node* MachineOperatorReducer::Int32Sub(Node* lhs, Node* rhs) {
99 1524 : Node* const node = graph()->NewNode(machine()->Int32Sub(), lhs, rhs);
100 1524 : Reduction const reduction = ReduceInt32Sub(node);
101 1524 : return reduction.Changed() ? reduction.replacement() : node;
102 : }
103 :
104 :
105 3447 : Node* MachineOperatorReducer::Int32Mul(Node* lhs, Node* rhs) {
106 6894 : return graph()->NewNode(machine()->Int32Mul(), lhs, rhs);
107 : }
108 :
109 :
110 4149 : 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 4149 : base::SignedDivisionByConstant(bit_cast<uint32_t>(divisor));
115 4149 : Node* quotient = graph()->NewNode(machine()->Int32MulHigh(), dividend,
116 : Uint32Constant(mag.multiplier));
117 4149 : if (divisor > 0 && bit_cast<int32_t>(mag.multiplier) < 0) {
118 1275 : quotient = Int32Add(quotient, dividend);
119 2874 : } else if (divisor < 0 && bit_cast<int32_t>(mag.multiplier) > 0) {
120 0 : quotient = Int32Sub(quotient, dividend);
121 : }
122 4149 : return Int32Add(Word32Sar(quotient, mag.shift), Word32Shr(dividend, 31));
123 : }
124 :
125 :
126 1422 : 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 1422 : dividend = Word32Shr(dividend, shift);
132 1422 : divisor >>= shift;
133 : // Compute the magic number for the (shifted) divisor.
134 : base::MagicNumbersForDivision<uint32_t> const mag =
135 1422 : base::UnsignedDivisionByConstant(divisor, shift);
136 1422 : Node* quotient = graph()->NewNode(machine()->Uint32MulHigh(), dividend,
137 1422 : Uint32Constant(mag.multiplier));
138 1422 : 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 1398 : quotient = Word32Shr(quotient, mag.shift);
145 : }
146 1422 : return quotient;
147 : }
148 :
149 :
150 : // Perform constant folding and strength reduction on machine operators.
151 163269373 : Reduction MachineOperatorReducer::Reduce(Node* node) {
152 163269373 : switch (node->opcode()) {
153 : case IrOpcode::kProjection:
154 390899 : return ReduceProjection(ProjectionIndexOf(node->op()), node->InputAt(0));
155 : case IrOpcode::kWord32And:
156 645360 : return ReduceWord32And(node);
157 : case IrOpcode::kWord32Or:
158 81303 : return ReduceWord32Or(node);
159 : case IrOpcode::kWord32Xor:
160 23722 : return ReduceWord32Xor(node);
161 : case IrOpcode::kWord32Shl:
162 41600 : return ReduceWord32Shl(node);
163 : case IrOpcode::kWord64Shl:
164 699951 : return ReduceWord64Shl(node);
165 : case IrOpcode::kWord32Shr:
166 81111 : return ReduceWord32Shr(node);
167 : case IrOpcode::kWord64Shr:
168 50050 : return ReduceWord64Shr(node);
169 : case IrOpcode::kWord32Sar:
170 39183 : return ReduceWord32Sar(node);
171 : case IrOpcode::kWord64Sar:
172 479112 : 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 1266737 : Int32BinopMatcher m(node);
184 1266737 : if (m.IsFoldable()) { // K == K => K
185 64870 : return ReplaceBool(m.left().Value() == m.right().Value());
186 : }
187 1236223 : if (m.left().IsInt32Sub() && m.right().Is(0)) { // x - y == 0 => x == y
188 838 : Int32BinopMatcher msub(m.left().node());
189 838 : node->ReplaceInput(0, msub.left().node());
190 838 : node->ReplaceInput(1, msub.right().node());
191 : return Changed(node);
192 : }
193 : // TODO(turbofan): fold HeapConstant, ExternalReference, pointer compares
194 1233894 : if (m.LeftEqualsRight()) return ReplaceBool(true); // x == x => true
195 1233872 : break;
196 : }
197 : case IrOpcode::kWord64Equal: {
198 2952591 : Int64BinopMatcher m(node);
199 2952592 : if (m.IsFoldable()) { // K == K => K
200 15529 : return ReplaceBool(m.left().Value() == m.right().Value());
201 : }
202 2957242 : 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 2949030 : if (m.LeftEqualsRight()) return ReplaceBool(true); // x == x => true
210 2939897 : break;
211 : }
212 : case IrOpcode::kInt32Add:
213 453967 : return ReduceInt32Add(node);
214 : case IrOpcode::kInt64Add:
215 1551908 : return ReduceInt64Add(node);
216 : case IrOpcode::kInt32Sub:
217 62838 : return ReduceInt32Sub(node);
218 : case IrOpcode::kInt64Sub:
219 313171 : return ReduceInt64Sub(node);
220 : case IrOpcode::kInt32Mul: {
221 46743 : Int32BinopMatcher m(node);
222 67478 : if (m.right().Is(0)) return Replace(m.right().node()); // x * 0 => 0
223 46378 : if (m.right().Is(1)) return Replace(m.left().node()); // x * 1 => x
224 46077 : if (m.IsFoldable()) { // K * K => K
225 : return ReplaceInt32(
226 18132 : base::MulWithWraparound(m.left().Value(), m.right().Value()));
227 : }
228 27945 : if (m.right().Is(-1)) { // x * -1 => 0 - x
229 70 : node->ReplaceInput(0, Int32Constant(0));
230 70 : node->ReplaceInput(1, m.left().node());
231 70 : NodeProperties::ChangeOp(node, machine()->Int32Sub());
232 : return Changed(node);
233 : }
234 27875 : if (m.right().IsPowerOf2()) { // x * 2^n => x << n
235 3734 : node->ReplaceInput(1, Int32Constant(WhichPowerOf2(m.right().Value())));
236 1867 : NodeProperties::ChangeOp(node, machine()->Word32Shl());
237 1867 : Reduction reduction = ReduceWord32Shl(node);
238 1867 : return reduction.Changed() ? reduction : Changed(node);
239 : }
240 26008 : break;
241 : }
242 : case IrOpcode::kInt32MulWithOverflow: {
243 9325 : Int32BinopMatcher m(node);
244 9325 : if (m.right().Is(2)) {
245 389 : node->ReplaceInput(1, m.left().node());
246 389 : NodeProperties::ChangeOp(node, machine()->Int32AddWithOverflow());
247 3535 : return Changed(node);
248 : }
249 8936 : 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 5790 : break;
256 : }
257 : case IrOpcode::kInt32Div:
258 20534 : return ReduceInt32Div(node);
259 : case IrOpcode::kUint32Div:
260 19323 : return ReduceUint32Div(node);
261 : case IrOpcode::kInt32Mod:
262 30527 : return ReduceInt32Mod(node);
263 : case IrOpcode::kUint32Mod:
264 21497 : return ReduceUint32Mod(node);
265 : case IrOpcode::kInt32LessThan: {
266 371033 : Int32BinopMatcher m(node);
267 371072 : if (m.IsFoldable()) { // K < K => K
268 40107 : return ReplaceBool(m.left().Value() < m.right().Value());
269 : }
270 351059 : if (m.LeftEqualsRight()) return ReplaceBool(false); // x < x => false
271 353252 : 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 69 : return ReplaceBool(true);
277 : }
278 : }
279 350978 : break;
280 : }
281 : case IrOpcode::kInt32LessThanOrEqual: {
282 49977 : Int32BinopMatcher m(node);
283 49977 : if (m.IsFoldable()) { // K <= K => K
284 35625 : return ReplaceBool(m.left().Value() <= m.right().Value());
285 : }
286 32167 : if (m.LeftEqualsRight()) return ReplaceBool(true); // x <= x => true
287 32162 : break;
288 : }
289 : case IrOpcode::kUint32LessThan: {
290 271654 : Uint32BinopMatcher m(node);
291 293402 : if (m.left().Is(kMaxUInt32)) return ReplaceBool(false); // M < x => false
292 271342 : if (m.right().Is(0)) return ReplaceBool(false); // x < 0 => false
293 270911 : if (m.IsFoldable()) { // K < K => K
294 20557 : return ReplaceBool(m.left().Value() < m.right().Value());
295 : }
296 250354 : if (m.LeftEqualsRight()) return ReplaceBool(false); // x < x => false
297 250203 : if (m.left().IsWord32Sar() && m.right().HasValue()) {
298 363 : Int32BinopMatcher mleft(m.left().node());
299 363 : if (mleft.right().HasValue()) {
300 : // (x >> K) < C => x < (C << K)
301 : // when C < (M >> K)
302 363 : const uint32_t c = m.right().Value();
303 363 : const uint32_t k = mleft.right().Value() & 0x1F;
304 363 : 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 249904 : break;
313 : }
314 : case IrOpcode::kUint32LessThanOrEqual: {
315 91622 : Uint32BinopMatcher m(node);
316 108774 : if (m.left().Is(0)) return ReplaceBool(true); // 0 <= x => true
317 91208 : if (m.right().Is(kMaxUInt32)) return ReplaceBool(true); // x <= M => true
318 90918 : if (m.IsFoldable()) { // K <= K => K
319 16442 : return ReplaceBool(m.left().Value() <= m.right().Value());
320 : }
321 74476 : if (m.LeftEqualsRight()) return ReplaceBool(true); // x <= x => true
322 74470 : 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 206342 : Float64BinopMatcher m(node);
362 206366 : if (m.IsFoldable()) { // K + K => K
363 22064 : return ReplaceFloat64(m.left().Value() + m.right().Value());
364 : }
365 195334 : break;
366 : }
367 : case IrOpcode::kFloat64Sub: {
368 39639 : Float64BinopMatcher m(node);
369 79793 : if (allow_signalling_nan_ && m.right().Is(0) &&
370 515 : (Double(m.right().Value()).Sign() > 0)) {
371 20671 : return Replace(m.left().node()); // x - 0 => x
372 : }
373 39369 : 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 38860 : 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 38381 : if (m.IsFoldable()) { // L - R => (L - R)
382 10989 : return ReplaceFloat64(m.left().Value() - m.right().Value());
383 : }
384 27392 : if (allow_signalling_nan_ && m.left().IsMinusZero()) {
385 : // -0.0 - round_down(-0.0 - R) => round_up(R)
386 16846 : 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 8424 : node->RemoveInput(0);
398 8424 : NodeProperties::ChangeOp(node, machine()->Float64Neg());
399 : return Changed(node);
400 : }
401 18968 : break;
402 : }
403 : case IrOpcode::kFloat64Mul: {
404 25398 : Float64BinopMatcher m(node);
405 50796 : if (allow_signalling_nan_ && m.right().Is(1))
406 9321 : return Replace(m.left().node()); // x * 1.0 => x
407 25349 : if (m.right().Is(-1)) { // x * -1.0 => -0.0 - x
408 8586 : node->ReplaceInput(0, Float64Constant(-0.0));
409 8586 : node->ReplaceInput(1, m.left().node());
410 8586 : NodeProperties::ChangeOp(node, machine()->Float64Sub());
411 : return Changed(node);
412 : }
413 16763 : 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 16756 : if (m.IsFoldable()) { // K * K => K
418 544 : return ReplaceFloat64(m.left().Value() * m.right().Value());
419 : }
420 16212 : 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 16077 : break;
426 : }
427 : case IrOpcode::kFloat64Div: {
428 37942 : Float64BinopMatcher m(node);
429 75884 : if (allow_signalling_nan_ && m.right().Is(1))
430 4897 : 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 37810 : 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 37810 : 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 37810 : if (m.IsFoldable()) { // K / K => K
441 : return ReplaceFloat64(
442 1890 : base::Divide(m.left().Value(), m.right().Value()));
443 : }
444 71840 : 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 35884 : 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 33045 : break;
458 : }
459 : case IrOpcode::kFloat64Mod: {
460 2313 : Float64BinopMatcher m(node);
461 2313 : if (m.right().Is(0)) { // x % 0 => NaN
462 25 : return ReplaceFloat64(std::numeric_limits<double>::quiet_NaN());
463 : }
464 2313 : if (m.right().IsNaN()) { // x % NaN => NaN
465 : return Replace(m.right().node());
466 : }
467 2313 : if (m.left().IsNaN()) { // NaN % x => NaN
468 : return Replace(m.left().node());
469 : }
470 2313 : if (m.IsFoldable()) { // K % K => K
471 25 : return ReplaceFloat64(Modulo(m.left().Value(), m.right().Value()));
472 : }
473 2288 : 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 335 : 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 539 : 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 11249 : Float64BinopMatcher m(node);
566 11249 : if (m.IsFoldable()) {
567 : return ReplaceFloat64(
568 21550 : base::ieee754::pow(m.left().Value(), m.right().Value()));
569 475 : } else if (m.right().Is(0.0)) { // x ** +-0.0 => 1.0
570 : return ReplaceFloat64(1.0);
571 473 : } 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 473 : } 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 473 : } 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 473 : } 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 473 : 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 13779 : 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 5242 : if (m.HasValue()) return ReplaceInt32(FastD2IChecked(m.Value()));
626 5114 : 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 1157 : if (m.HasValue()) return ReplaceInt32(FastD2UI(m.Value()));
638 1061 : if (m.IsChangeUint32ToFloat64()) return Replace(m.node()->InputAt(0));
639 : break;
640 : }
641 : case IrOpcode::kChangeInt32ToFloat64: {
642 : Int32Matcher m(node->InputAt(0));
643 388879 : if (m.HasValue()) return ReplaceFloat64(FastI2D(m.Value()));
644 : break;
645 : }
646 : case IrOpcode::kChangeInt32ToInt64: {
647 : Int32Matcher m(node->InputAt(0));
648 382191 : if (m.HasValue()) return ReplaceInt64(m.Value());
649 : break;
650 : }
651 : case IrOpcode::kChangeInt64ToFloat64: {
652 : Int64Matcher m(node->InputAt(0));
653 656 : if (m.HasValue()) return ReplaceFloat64(static_cast<double>(m.Value()));
654 552 : if (m.IsChangeFloat64ToInt64()) return Replace(m.node()->InputAt(0));
655 : break;
656 : }
657 : case IrOpcode::kChangeUint32ToFloat64: {
658 : Uint32Matcher m(node->InputAt(0));
659 7012 : if (m.HasValue()) return ReplaceFloat64(FastUI2D(m.Value()));
660 : break;
661 : }
662 : case IrOpcode::kChangeUint32ToUint64: {
663 : Uint32Matcher m(node->InputAt(0));
664 303496 : 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 28186 : if (m.HasValue()) return ReplaceInt32(DoubleToInt32(m.Value()));
670 27939 : if (m.IsChangeInt32ToFloat64()) return Replace(m.node()->InputAt(0));
671 : return NoChange();
672 : }
673 : case IrOpcode::kTruncateInt64ToInt32: {
674 : Int64Matcher m(node->InputAt(0));
675 438131 : if (m.HasValue()) return ReplaceInt32(static_cast<int32_t>(m.Value()));
676 428329 : if (m.IsChangeInt32ToInt64()) return Replace(m.node()->InputAt(0));
677 : break;
678 : }
679 : case IrOpcode::kTruncateFloat64ToFloat32: {
680 : Float64Matcher m(node->InputAt(0));
681 9074 : 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 8394 : 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 129695 : if (m.HasValue()) {
695 132 : return ReplaceInt32(DoubleToInt32(m.Value()));
696 : }
697 129563 : 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 3256134 : return ReduceStore(node);
707 : case IrOpcode::kFloat64Equal:
708 : case IrOpcode::kFloat64LessThan:
709 : case IrOpcode::kFloat64LessThanOrEqual:
710 360752 : return ReduceFloat64Compare(node);
711 : case IrOpcode::kFloat64RoundDown:
712 81773 : return ReduceFloat64RoundDown(node);
713 : case IrOpcode::kBitcastTaggedToWord: {
714 : NodeMatcher m(node->InputAt(0));
715 1163754 : 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 560930 : Reduction MachineOperatorReducer::ReduceInt32Add(Node* node) {
728 : DCHECK_EQ(IrOpcode::kInt32Add, node->opcode());
729 560930 : Int32BinopMatcher m(node);
730 560954 : if (m.right().Is(0)) return Replace(m.left().node()); // x + 0 => x
731 537302 : if (m.IsFoldable()) { // K + K => K
732 : return ReplaceInt32(
733 38157 : base::AddWithWraparound(m.left().Value(), m.right().Value()));
734 : }
735 499145 : if (m.left().IsInt32Sub()) {
736 1479 : Int32BinopMatcher mleft(m.left().node());
737 1479 : 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 499023 : 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 1807085 : Reduction MachineOperatorReducer::ReduceInt64Add(Node* node) {
758 : DCHECK_EQ(IrOpcode::kInt64Add, node->opcode());
759 1807085 : Int64BinopMatcher m(node);
760 1807085 : if (m.right().Is(0)) return Replace(m.left().node()); // x + 0 => 0
761 1794229 : if (m.IsFoldable()) {
762 : return ReplaceInt64(
763 78381 : base::AddWithWraparound(m.left().Value(), m.right().Value()));
764 : }
765 : return NoChange();
766 : }
767 :
768 64575 : Reduction MachineOperatorReducer::ReduceInt32Sub(Node* node) {
769 : DCHECK_EQ(IrOpcode::kInt32Sub, node->opcode());
770 64575 : Int32BinopMatcher m(node);
771 64575 : if (m.right().Is(0)) return Replace(m.left().node()); // x - 0 => x
772 63992 : if (m.IsFoldable()) { // K - K => K
773 : return ReplaceInt32(
774 19416 : base::SubWithWraparound(m.left().Value(), m.right().Value()));
775 : }
776 44576 : if (m.LeftEqualsRight()) return ReplaceInt32(0); // x - x => 0
777 44576 : if (m.right().HasValue()) { // x - K => x + -K
778 13662 : node->ReplaceInput(
779 13662 : 1, Int32Constant(base::NegateWithWraparound(m.right().Value())));
780 13662 : NodeProperties::ChangeOp(node, machine()->Int32Add());
781 13662 : Reduction const reduction = ReduceInt32Add(node);
782 13662 : return reduction.Changed() ? reduction : Changed(node);
783 : }
784 : return NoChange();
785 : }
786 :
787 313170 : Reduction MachineOperatorReducer::ReduceInt64Sub(Node* node) {
788 : DCHECK_EQ(IrOpcode::kInt64Sub, node->opcode());
789 313170 : Int64BinopMatcher m(node);
790 313170 : if (m.right().Is(0)) return Replace(m.left().node()); // x - 0 => x
791 306639 : if (m.IsFoldable()) { // K - K => K
792 : return ReplaceInt64(
793 35260 : base::SubWithWraparound(m.left().Value(), m.right().Value()));
794 : }
795 271379 : if (m.LeftEqualsRight()) return Replace(Int64Constant(0)); // x - x => 0
796 271374 : if (m.right().HasValue()) { // x - K => x + -K
797 510354 : node->ReplaceInput(
798 255177 : 1, Int64Constant(base::NegateWithWraparound(m.right().Value())));
799 255178 : NodeProperties::ChangeOp(node, machine()->Int64Add());
800 255178 : Reduction const reduction = ReduceInt64Add(node);
801 255178 : return reduction.Changed() ? reduction : Changed(node);
802 : }
803 : return NoChange();
804 : }
805 :
806 20534 : Reduction MachineOperatorReducer::ReduceInt32Div(Node* node) {
807 20534 : Int32BinopMatcher m(node);
808 20534 : if (m.left().Is(0)) return Replace(m.left().node()); // 0 / x => 0
809 20249 : if (m.right().Is(0)) return Replace(m.right().node()); // x / 0 => 0
810 20248 : if (m.right().Is(1)) return Replace(m.left().node()); // x / 1 => x
811 19928 : if (m.IsFoldable()) { // K / K => K
812 : return ReplaceInt32(
813 15960 : base::bits::SignedDiv32(m.left().Value(), m.right().Value()));
814 : }
815 3968 : 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 3967 : 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 3935 : if (m.right().HasValue()) {
827 2811 : int32_t const divisor = m.right().Value();
828 : Node* const dividend = m.left().node();
829 : Node* quotient = dividend;
830 2811 : if (base::bits::IsPowerOfTwo(Abs(divisor))) {
831 744 : uint32_t const shift = WhichPowerOf2(Abs(divisor));
832 : DCHECK_NE(0u, shift);
833 744 : if (shift > 1) {
834 633 : quotient = Word32Sar(quotient, 31);
835 : }
836 744 : quotient = Int32Add(Word32Shr(quotient, 32u - shift), dividend);
837 744 : quotient = Word32Sar(quotient, shift);
838 : } else {
839 2067 : quotient = Int32Div(quotient, Abs(divisor));
840 : }
841 2811 : if (divisor < 0) {
842 1279 : node->ReplaceInput(0, Int32Constant(0));
843 1279 : node->ReplaceInput(1, quotient);
844 1279 : node->TrimInputCount(2);
845 1279 : NodeProperties::ChangeOp(node, machine()->Int32Sub());
846 : return Changed(node);
847 : }
848 : return Replace(quotient);
849 : }
850 : return NoChange();
851 : }
852 :
853 :
854 19323 : Reduction MachineOperatorReducer::ReduceUint32Div(Node* node) {
855 19323 : Uint32BinopMatcher m(node);
856 19323 : 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 30527 : Reduction MachineOperatorReducer::ReduceInt32Mod(Node* node) {
884 30527 : Int32BinopMatcher m(node);
885 30527 : if (m.left().Is(0)) return Replace(m.left().node()); // 0 % x => 0
886 30140 : if (m.right().Is(0)) return Replace(m.right().node()); // x % 0 => 0
887 30040 : if (m.right().Is(1)) return ReplaceInt32(0); // x % 1 => 0
888 29728 : if (m.right().Is(-1)) return ReplaceInt32(0); // x % -1 => 0
889 29442 : if (m.LeftEqualsRight()) return ReplaceInt32(0); // x % x => 0
890 29441 : if (m.IsFoldable()) { // K % K => K
891 : return ReplaceInt32(
892 25506 : base::bits::SignedMod32(m.left().Value(), m.right().Value()));
893 : }
894 3935 : if (m.right().HasValue()) {
895 : Node* const dividend = m.left().node();
896 2832 : uint32_t const divisor = Abs(m.right().Value());
897 2832 : if (base::bits::IsPowerOfTwo(divisor)) {
898 750 : 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 1500 : BranchHint::kFalse);
903 : return Replace(
904 : d.Phi(MachineRepresentation::kWord32,
905 : Int32Sub(zero, Word32And(Int32Sub(zero, dividend), mask)),
906 750 : Word32And(dividend, mask)));
907 : } else {
908 2082 : Node* quotient = Int32Div(dividend, divisor);
909 : DCHECK_EQ(dividend, node->InputAt(0));
910 2082 : node->ReplaceInput(1, Int32Mul(quotient, Int32Constant(divisor)));
911 2082 : node->TrimInputCount(2);
912 2082 : NodeProperties::ChangeOp(node, machine()->Int32Sub());
913 : }
914 : return Changed(node);
915 : }
916 : return NoChange();
917 : }
918 :
919 :
920 21497 : Reduction MachineOperatorReducer::ReduceUint32Mod(Node* node) {
921 21497 : Uint32BinopMatcher m(node);
922 21497 : if (m.left().Is(0)) return Replace(m.left().node()); // 0 % x => 0
923 21117 : if (m.right().Is(0)) return Replace(m.right().node()); // x % 0 => 0
924 21069 : if (m.right().Is(1)) return ReplaceUint32(0); // x % 1 => 0
925 20726 : if (m.LeftEqualsRight()) return ReplaceInt32(0); // x % x => 0
926 20724 : if (m.IsFoldable()) { // K % K => K
927 : return ReplaceUint32(
928 18186 : base::bits::UnsignedMod32(m.left().Value(), m.right().Value()));
929 : }
930 2538 : if (m.right().HasValue()) {
931 : Node* const dividend = m.left().node();
932 1895 : uint32_t const divisor = m.right().Value();
933 1895 : if (base::bits::IsPowerOfTwo(divisor)) { // x % 2^n => x & 2^n-1
934 1060 : node->ReplaceInput(1, Uint32Constant(m.right().Value() - 1));
935 530 : node->TrimInputCount(2);
936 530 : NodeProperties::ChangeOp(node, machine()->Word32And());
937 : } else {
938 1365 : Node* quotient = Uint32Div(dividend, divisor);
939 : DCHECK_EQ(dividend, node->InputAt(0));
940 1365 : node->ReplaceInput(1, Int32Mul(quotient, Uint32Constant(divisor)));
941 1365 : node->TrimInputCount(2);
942 1365 : NodeProperties::ChangeOp(node, machine()->Int32Sub());
943 : }
944 : return Changed(node);
945 : }
946 : return NoChange();
947 : }
948 :
949 :
950 3256133 : Reduction MachineOperatorReducer::ReduceStore(Node* node) {
951 : NodeMatcher nm(node);
952 : MachineRepresentation rep;
953 : int value_input;
954 3256133 : if (nm.IsStore()) {
955 3256133 : 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 3256132 : switch (value->opcode()) {
966 : case IrOpcode::kWord32And: {
967 7391 : Uint32BinopMatcher m(value);
968 20080 : if (m.right().HasValue() && ((rep == MachineRepresentation::kWord8 &&
969 7205 : (m.right().Value() & 0xFF) == 0xFF) ||
970 1357 : (rep == MachineRepresentation::kWord16 &&
971 1357 : (m.right().Value() & 0xFFFF) == 0xFFFF))) {
972 6377 : node->ReplaceInput(value_input, m.left().node());
973 6377 : 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 390899 : Reduction MachineOperatorReducer::ReduceProjection(size_t index, Node* node) {
999 390899 : switch (node->opcode()) {
1000 : case IrOpcode::kInt32AddWithOverflow: {
1001 : DCHECK(index == 0 || index == 1);
1002 259720 : Int32BinopMatcher m(node);
1003 259744 : 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 239738 : if (m.right().Is(0)) {
1010 32 : return Replace(index == 0 ? m.left().node() : m.right().node());
1011 : }
1012 239706 : break;
1013 : }
1014 : case IrOpcode::kInt32SubWithOverflow: {
1015 : DCHECK(index == 0 || index == 1);
1016 67125 : Int32BinopMatcher m(node);
1017 67125 : 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 47069 : if (m.right().Is(0)) {
1024 2 : return Replace(index == 0 ? m.left().node() : m.right().node());
1025 : }
1026 47067 : break;
1027 : }
1028 : case IrOpcode::kInt32MulWithOverflow: {
1029 : DCHECK(index == 0 || index == 1);
1030 31509 : Int32BinopMatcher m(node);
1031 31509 : 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 11199 : if (m.right().Is(0)) {
1038 : return Replace(m.right().node());
1039 : }
1040 11111 : if (m.right().Is(1)) {
1041 72 : return index == 0 ? Replace(m.left().node()) : ReplaceInt32(0);
1042 : }
1043 11039 : break;
1044 : }
1045 : default:
1046 : break;
1047 : }
1048 : return NoChange();
1049 : }
1050 :
1051 :
1052 116930 : Reduction MachineOperatorReducer::ReduceWord32Shifts(Node* node) {
1053 : DCHECK((node->opcode() == IrOpcode::kWord32Shl) ||
1054 : (node->opcode() == IrOpcode::kWord32Shr) ||
1055 : (node->opcode() == IrOpcode::kWord32Sar));
1056 116930 : 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 116615 : Int32BinopMatcher m(node);
1060 116615 : if (m.right().IsWord32And()) {
1061 1776 : Int32BinopMatcher mright(m.right().node());
1062 1776 : if (mright.right().Is(0x1F)) {
1063 793 : node->ReplaceInput(1, mright.left().node());
1064 793 : return Changed(node);
1065 : }
1066 : }
1067 : }
1068 : return NoChange();
1069 : }
1070 :
1071 :
1072 43467 : Reduction MachineOperatorReducer::ReduceWord32Shl(Node* node) {
1073 : DCHECK_EQ(IrOpcode::kWord32Shl, node->opcode());
1074 43467 : Int32BinopMatcher m(node);
1075 43467 : if (m.right().Is(0)) return Replace(m.left().node()); // x << 0 => x
1076 43090 : if (m.IsFoldable()) { // K << K => K
1077 : return ReplaceInt32(
1078 11801 : base::ShlWithWraparound(m.left().Value(), m.right().Value()));
1079 : }
1080 31289 : if (m.right().IsInRange(1, 31)) {
1081 : // (x >>> K) << K => x & ~(2^K - 1)
1082 : // (x >> K) << K => x & ~(2^K - 1)
1083 27764 : 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 28232 : return ReduceWord32Shifts(node);
1096 : }
1097 :
1098 699950 : Reduction MachineOperatorReducer::ReduceWord64Shl(Node* node) {
1099 : DCHECK_EQ(IrOpcode::kWord64Shl, node->opcode());
1100 699950 : Int64BinopMatcher m(node);
1101 699950 : if (m.right().Is(0)) return Replace(m.left().node()); // x << 0 => x
1102 699540 : if (m.IsFoldable()) { // K << K => K
1103 : return ReplaceInt64(
1104 89513 : base::ShlWithWraparound(m.left().Value(), m.right().Value()));
1105 : }
1106 : return NoChange();
1107 : }
1108 :
1109 81111 : Reduction MachineOperatorReducer::ReduceWord32Shr(Node* node) {
1110 81111 : Uint32BinopMatcher m(node);
1111 81111 : if (m.right().Is(0)) return Replace(m.left().node()); // x >>> 0 => x
1112 68481 : if (m.IsFoldable()) { // K >>> K => K
1113 9090 : return ReplaceInt32(m.left().Value() >> (m.right().Value() & 31));
1114 : }
1115 59391 : if (m.left().IsWord32And() && m.right().HasValue()) {
1116 24365 : Uint32BinopMatcher mleft(m.left().node());
1117 24365 : if (mleft.right().HasValue()) {
1118 24365 : uint32_t shift = m.right().Value() & 31;
1119 24365 : uint32_t mask = mleft.right().Value();
1120 24365 : if ((mask >> shift) == 0) {
1121 : // (m >>> s) == 0 implies ((x & m) >>> s) == 0
1122 31 : return ReplaceInt32(0);
1123 : }
1124 : }
1125 : }
1126 59360 : 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 39183 : Reduction MachineOperatorReducer::ReduceWord32Sar(Node* node) {
1140 39183 : Int32BinopMatcher m(node);
1141 39183 : if (m.right().Is(0)) return Replace(m.left().node()); // x >> 0 => x
1142 38758 : if (m.IsFoldable()) { // K >> K => K
1143 9369 : return ReplaceInt32(m.left().Value() >> (m.right().Value() & 31));
1144 : }
1145 29389 : 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 29338 : return ReduceWord32Shifts(node);
1172 : }
1173 :
1174 479112 : Reduction MachineOperatorReducer::ReduceWord64Sar(Node* node) {
1175 479112 : Int64BinopMatcher m(node);
1176 479112 : if (m.right().Is(0)) return Replace(m.left().node()); // x >> 0 => x
1177 478702 : if (m.IsFoldable()) {
1178 34327 : return ReplaceInt64(m.left().Value() >> (m.right().Value() & 63));
1179 : }
1180 : return NoChange();
1181 : }
1182 :
1183 756719 : Reduction MachineOperatorReducer::ReduceWord32And(Node* node) {
1184 : DCHECK_EQ(IrOpcode::kWord32And, node->opcode());
1185 756719 : Int32BinopMatcher m(node);
1186 756719 : if (m.right().Is(0)) return Replace(m.right().node()); // x & 0 => 0
1187 755018 : if (m.right().Is(-1)) return Replace(m.left().node()); // x & -1 => x
1188 755772 : if (m.left().IsComparison() && m.right().Is(1)) { // CMP & 1 => CMP
1189 : return Replace(m.left().node());
1190 : }
1191 754422 : if (m.IsFoldable()) { // K & K => K
1192 23288 : return ReplaceInt32(m.left().Value() & m.right().Value());
1193 : }
1194 731134 : if (m.LeftEqualsRight()) return Replace(m.left().node()); // x & x => x
1195 731049 : if (m.left().IsWord32And() && m.right().HasValue()) {
1196 22647 : Int32BinopMatcher mleft(m.left().node());
1197 22647 : 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 711351 : if (m.right().IsNegativePowerOf2()) {
1206 254023 : int32_t const mask = m.right().Value();
1207 : int32_t const neg_mask = base::NegateWithWraparound(mask);
1208 254023 : 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 251881 : } 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 157075 : } 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 53470 : Reduction MachineOperatorReducer::TryMatchWord32Ror(Node* node) {
1287 : DCHECK(IrOpcode::kWord32Or == node->opcode() ||
1288 : IrOpcode::kWord32Xor == node->opcode());
1289 53470 : 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 60393 : if (m.left().IsWord32Shl() && m.right().IsWord32Shr()) {
1299 : shl = m.left().node();
1300 : shr = m.right().node();
1301 52994 : } 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 937 : Int32BinopMatcher mshl(shl);
1309 937 : Int32BinopMatcher mshr(shr);
1310 937 : if (mshl.left().node() != mshr.left().node()) return NoChange();
1311 :
1312 636 : 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 254 : if (mshl.right().IsInt32Sub()) {
1319 : sub = mshl.right().node();
1320 : y = mshr.right().node();
1321 211 : } else if (mshr.right().IsInt32Sub()) {
1322 : sub = mshr.right().node();
1323 : y = mshl.right().node();
1324 : } else {
1325 182 : 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 81303 : Reduction MachineOperatorReducer::ReduceWord32Or(Node* node) {
1339 : DCHECK_EQ(IrOpcode::kWord32Or, node->opcode());
1340 81303 : Int32BinopMatcher m(node);
1341 81303 : if (m.right().Is(0)) return Replace(m.left().node()); // x | 0 => x
1342 66461 : if (m.right().Is(-1)) return Replace(m.right().node()); // x | -1 => -1
1343 63059 : if (m.IsFoldable()) { // K | K => K
1344 16315 : return ReplaceInt32(m.left().Value() | m.right().Value());
1345 : }
1346 46744 : if (m.LeftEqualsRight()) return Replace(m.left().node()); // x | x => x
1347 :
1348 46713 : return TryMatchWord32Ror(node);
1349 : }
1350 :
1351 23722 : Reduction MachineOperatorReducer::ReduceWord32Xor(Node* node) {
1352 : DCHECK_EQ(IrOpcode::kWord32Xor, node->opcode());
1353 23722 : Int32BinopMatcher m(node);
1354 23722 : if (m.right().Is(0)) return Replace(m.left().node()); // x ^ 0 => x
1355 23397 : if (m.IsFoldable()) { // K ^ K => K
1356 16615 : return ReplaceInt32(m.left().Value() ^ m.right().Value());
1357 : }
1358 6782 : if (m.LeftEqualsRight()) return ReplaceInt32(0); // x ^ x => 0
1359 7071 : 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 6757 : 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 328492 : if (m.HasValue()) {
1399 104513 : double v = m.Value();
1400 104513 : return DoubleToFloat32(v) == v;
1401 : }
1402 : return false;
1403 : }
1404 :
1405 : } // namespace
1406 :
1407 :
1408 360751 : Reduction MachineOperatorReducer::ReduceFloat64Compare(Node* node) {
1409 : DCHECK(IrOpcode::kFloat64Equal == node->opcode() ||
1410 : IrOpcode::kFloat64LessThan == node->opcode() ||
1411 : IrOpcode::kFloat64LessThanOrEqual == node->opcode());
1412 360751 : Float64BinopMatcher m(node);
1413 360751 : 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 329926 : } else if ((m.left().IsChangeFloat32ToFloat64() &&
1425 327711 : m.right().IsChangeFloat32ToFloat64()) ||
1426 1161 : (m.left().IsChangeFloat32ToFloat64() &&
1427 655569 : IsFloat64RepresentableAsFloat32(m.right())) ||
1428 104027 : (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 1147 : switch (node->opcode()) {
1436 : case IrOpcode::kFloat64Equal:
1437 288 : NodeProperties::ChangeOp(node, machine()->Float32Equal());
1438 288 : 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 1387 : node->ReplaceInput(
1449 : 0, m.left().HasValue()
1450 240 : ? Float32Constant(static_cast<float>(m.left().Value()))
1451 1147 : : m.left().InputAt(0));
1452 1527 : node->ReplaceInput(
1453 : 1, m.right().HasValue()
1454 380 : ? Float32Constant(static_cast<float>(m.right().Value()))
1455 1147 : : m.right().InputAt(0));
1456 : return Changed(node);
1457 : }
1458 : return NoChange();
1459 : }
1460 :
1461 81773 : Reduction MachineOperatorReducer::ReduceFloat64RoundDown(Node* node) {
1462 : DCHECK_EQ(IrOpcode::kFloat64RoundDown, node->opcode());
1463 : Float64Matcher m(node->InputAt(0));
1464 81773 : 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 122004 : } // namespace v8
|