Line data Source code
1 : // Copyright 2014 the V8 project authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
5 : #include "src/compiler/machine-operator-reducer.h"
6 :
7 : #include "src/base/bits.h"
8 : #include "src/base/division-by-constant.h"
9 : #include "src/base/ieee754.h"
10 : #include "src/base/overflowing-math.h"
11 : #include "src/compiler/diamond.h"
12 : #include "src/compiler/graph.h"
13 : #include "src/compiler/machine-graph.h"
14 : #include "src/compiler/node-matchers.h"
15 : #include "src/compiler/node-properties.h"
16 : #include "src/conversions-inl.h"
17 :
18 : namespace v8 {
19 : namespace internal {
20 : namespace compiler {
21 :
22 1670156 : MachineOperatorReducer::MachineOperatorReducer(Editor* editor,
23 : MachineGraph* mcgraph,
24 : bool allow_signalling_nan)
25 : : AdvancedReducer(editor),
26 : mcgraph_(mcgraph),
27 1670156 : allow_signalling_nan_(allow_signalling_nan) {}
28 :
29 : MachineOperatorReducer::~MachineOperatorReducer() = default;
30 :
31 :
32 66847 : Node* MachineOperatorReducer::Float32Constant(volatile float value) {
33 200541 : return graph()->NewNode(common()->Float32Constant(value));
34 : }
35 :
36 :
37 95898 : Node* MachineOperatorReducer::Float64Constant(volatile double value) {
38 191796 : return mcgraph()->Float64Constant(value);
39 : }
40 :
41 :
42 544452 : Node* MachineOperatorReducer::Int32Constant(int32_t value) {
43 544452 : return mcgraph()->Int32Constant(value);
44 : }
45 :
46 :
47 547785 : Node* MachineOperatorReducer::Int64Constant(int64_t value) {
48 1095569 : return graph()->NewNode(common()->Int64Constant(value));
49 : }
50 :
51 0 : Node* MachineOperatorReducer::Float64Mul(Node* lhs, Node* rhs) {
52 0 : return graph()->NewNode(machine()->Float64Mul(), lhs, rhs);
53 : }
54 :
55 0 : Node* MachineOperatorReducer::Float64PowHalf(Node* value) {
56 : value =
57 0 : graph()->NewNode(machine()->Float64Add(), Float64Constant(0.0), value);
58 : Diamond d(graph(), common(),
59 : graph()->NewNode(machine()->Float64LessThanOrEqual(), value,
60 : Float64Constant(-V8_INFINITY)),
61 0 : BranchHint::kFalse);
62 : return d.Phi(MachineRepresentation::kFloat64, Float64Constant(V8_INFINITY),
63 0 : graph()->NewNode(machine()->Float64Sqrt(), value));
64 : }
65 :
66 88496 : Node* MachineOperatorReducer::Word32And(Node* lhs, Node* rhs) {
67 88496 : Node* const node = graph()->NewNode(machine()->Word32And(), lhs, rhs);
68 88496 : Reduction const reduction = ReduceWord32And(node);
69 88496 : return reduction.Changed() ? reduction.replacement() : node;
70 : }
71 :
72 :
73 4962 : Node* MachineOperatorReducer::Word32Sar(Node* lhs, uint32_t rhs) {
74 4962 : if (rhs == 0) return lhs;
75 9626 : return graph()->NewNode(machine()->Word32Sar(), lhs, Uint32Constant(rhs));
76 : }
77 :
78 :
79 6795 : Node* MachineOperatorReducer::Word32Shr(Node* lhs, uint32_t rhs) {
80 6795 : if (rhs == 0) return lhs;
81 11768 : return graph()->NewNode(machine()->Word32Shr(), lhs, Uint32Constant(rhs));
82 : }
83 :
84 :
85 12 : Node* MachineOperatorReducer::Word32Equal(Node* lhs, Node* rhs) {
86 24 : return graph()->NewNode(machine()->Word32Equal(), lhs, rhs);
87 : }
88 :
89 :
90 5553 : Node* MachineOperatorReducer::Int32Add(Node* lhs, Node* rhs) {
91 5553 : Node* const node = graph()->NewNode(machine()->Int32Add(), lhs, rhs);
92 5553 : Reduction const reduction = ReduceInt32Add(node);
93 5553 : return reduction.Changed() ? reduction.replacement() : node;
94 : }
95 :
96 :
97 1416 : Node* MachineOperatorReducer::Int32Sub(Node* lhs, Node* rhs) {
98 1416 : Node* const node = graph()->NewNode(machine()->Int32Sub(), lhs, rhs);
99 1416 : Reduction const reduction = ReduceInt32Sub(node);
100 1416 : return reduction.Changed() ? reduction.replacement() : node;
101 : }
102 :
103 :
104 3000 : Node* MachineOperatorReducer::Int32Mul(Node* lhs, Node* rhs) {
105 6000 : return graph()->NewNode(machine()->Int32Mul(), lhs, rhs);
106 : }
107 :
108 :
109 3716 : Node* MachineOperatorReducer::Int32Div(Node* dividend, int32_t divisor) {
110 : DCHECK_NE(0, divisor);
111 : DCHECK_NE(std::numeric_limits<int32_t>::min(), divisor);
112 : base::MagicNumbersForDivision<uint32_t> const mag =
113 3716 : base::SignedDivisionByConstant(bit_cast<uint32_t>(divisor));
114 : Node* quotient = graph()->NewNode(machine()->Int32MulHigh(), dividend,
115 3716 : Uint32Constant(mag.multiplier));
116 7432 : if (divisor > 0 && bit_cast<int32_t>(mag.multiplier) < 0) {
117 1140 : quotient = Int32Add(quotient, dividend);
118 2576 : } else if (divisor < 0 && bit_cast<int32_t>(mag.multiplier) > 0) {
119 0 : quotient = Int32Sub(quotient, dividend);
120 : }
121 3716 : return Int32Add(Word32Sar(quotient, mag.shift), Word32Shr(dividend, 31));
122 : }
123 :
124 :
125 1191 : Node* MachineOperatorReducer::Uint32Div(Node* dividend, uint32_t divisor) {
126 : DCHECK_LT(0u, divisor);
127 : // If the divisor is even, we can avoid using the expensive fixup by shifting
128 : // the dividend upfront.
129 : unsigned const shift = base::bits::CountTrailingZeros(divisor);
130 1191 : dividend = Word32Shr(dividend, shift);
131 1191 : divisor >>= shift;
132 : // Compute the magic number for the (shifted) divisor.
133 : base::MagicNumbersForDivision<uint32_t> const mag =
134 1191 : base::UnsignedDivisionByConstant(divisor, shift);
135 : Node* quotient = graph()->NewNode(machine()->Uint32MulHigh(), dividend,
136 2382 : Uint32Constant(mag.multiplier));
137 1191 : if (mag.add) {
138 : DCHECK_LE(1u, mag.shift);
139 : quotient = Word32Shr(
140 : Int32Add(Word32Shr(Int32Sub(dividend, quotient), 1), quotient),
141 24 : mag.shift - 1);
142 : } else {
143 1167 : quotient = Word32Shr(quotient, mag.shift);
144 : }
145 1191 : return quotient;
146 : }
147 :
148 :
149 : // Perform constant folding and strength reduction on machine operators.
150 124659130 : Reduction MachineOperatorReducer::Reduce(Node* node) {
151 124659130 : switch (node->opcode()) {
152 : case IrOpcode::kProjection:
153 249503 : return ReduceProjection(ProjectionIndexOf(node->op()), node->InputAt(0));
154 : case IrOpcode::kWord32And:
155 520166 : return ReduceWord32And(node);
156 : case IrOpcode::kWord32Or:
157 78040 : return ReduceWord32Or(node);
158 : case IrOpcode::kWord32Xor:
159 23909 : return ReduceWord32Xor(node);
160 : case IrOpcode::kWord32Shl:
161 43412 : return ReduceWord32Shl(node);
162 : case IrOpcode::kWord64Shl:
163 613508 : return ReduceWord64Shl(node);
164 : case IrOpcode::kWord32Shr:
165 80829 : return ReduceWord32Shr(node);
166 : case IrOpcode::kWord64Shr:
167 49142 : return ReduceWord64Shr(node);
168 : case IrOpcode::kWord32Sar:
169 30895 : return ReduceWord32Sar(node);
170 : case IrOpcode::kWord64Sar:
171 338152 : return ReduceWord64Sar(node);
172 : case IrOpcode::kWord32Ror: {
173 1887 : Int32BinopMatcher m(node);
174 3424 : if (m.right().Is(0)) return Replace(m.left().node()); // x ror 0 => x
175 1838 : if (m.IsFoldable()) { // K ror K => K
176 : return ReplaceInt32(
177 2976 : base::bits::RotateRight32(m.left().Value(), m.right().Value()));
178 : }
179 350 : break;
180 : }
181 : case IrOpcode::kWord32Equal: {
182 981121 : Int32BinopMatcher m(node);
183 981121 : if (m.IsFoldable()) { // K == K => K
184 64649 : return ReplaceBool(m.left().Value() == m.right().Value());
185 : }
186 949961 : if (m.left().IsInt32Sub() && m.right().Is(0)) { // x - y == 0 => x == y
187 738 : Int32BinopMatcher msub(m.left().node());
188 738 : node->ReplaceInput(0, msub.left().node());
189 738 : node->ReplaceInput(1, msub.right().node());
190 : return Changed(node);
191 : }
192 : // TODO(turbofan): fold HeapConstant, ExternalReference, pointer compares
193 948434 : if (m.LeftEqualsRight()) return ReplaceBool(true); // x == x => true
194 948421 : break;
195 : }
196 : case IrOpcode::kWord64Equal: {
197 1964162 : Int64BinopMatcher m(node);
198 1964160 : if (m.IsFoldable()) { // K == K => K
199 11058 : return ReplaceBool(m.left().Value() == m.right().Value());
200 : }
201 1970874 : if (m.left().IsInt64Sub() && m.right().Is(0)) { // x - y == 0 => x == y
202 728 : Int64BinopMatcher msub(m.left().node());
203 728 : node->ReplaceInput(0, msub.left().node());
204 728 : node->ReplaceInput(1, msub.right().node());
205 : return Changed(node);
206 : }
207 : // TODO(turbofan): fold HeapConstant, ExternalReference, pointer compares
208 1962830 : if (m.LeftEqualsRight()) return ReplaceBool(true); // x == x => true
209 1953704 : break;
210 : }
211 : case IrOpcode::kInt32Add:
212 389159 : return ReduceInt32Add(node);
213 : case IrOpcode::kInt64Add:
214 1648160 : return ReduceInt64Add(node);
215 : case IrOpcode::kInt32Sub:
216 53913 : return ReduceInt32Sub(node);
217 : case IrOpcode::kInt64Sub:
218 316394 : return ReduceInt64Sub(node);
219 : case IrOpcode::kInt32Mul: {
220 41997 : Int32BinopMatcher m(node);
221 62598 : if (m.right().Is(0)) return Replace(m.right().node()); // x * 0 => 0
222 41633 : if (m.right().Is(1)) return Replace(m.left().node()); // x * 1 => x
223 41332 : if (m.IsFoldable()) { // K * K => K
224 : return ReplaceInt32(
225 18163 : base::MulWithWraparound(m.left().Value(), m.right().Value()));
226 : }
227 23169 : if (m.right().Is(-1)) { // x * -1 => 0 - x
228 69 : node->ReplaceInput(0, Int32Constant(0));
229 69 : node->ReplaceInput(1, m.left().node());
230 69 : NodeProperties::ChangeOp(node, machine()->Int32Sub());
231 : return Changed(node);
232 : }
233 23100 : if (m.right().IsPowerOf2()) { // x * 2^n => x << n
234 3408 : node->ReplaceInput(1, Int32Constant(WhichPowerOf2(m.right().Value())));
235 1704 : NodeProperties::ChangeOp(node, machine()->Word32Shl());
236 1704 : Reduction reduction = ReduceWord32Shl(node);
237 1704 : return reduction.Changed() ? reduction : Changed(node);
238 : }
239 21396 : break;
240 : }
241 : case IrOpcode::kInt32MulWithOverflow: {
242 7166 : Int32BinopMatcher m(node);
243 7166 : if (m.right().Is(2)) {
244 187 : node->ReplaceInput(1, m.left().node());
245 187 : NodeProperties::ChangeOp(node, machine()->Int32AddWithOverflow());
246 3337 : return Changed(node);
247 : }
248 6979 : if (m.right().Is(-1)) {
249 3150 : node->ReplaceInput(0, Int32Constant(0));
250 3150 : node->ReplaceInput(1, m.left().node());
251 3150 : NodeProperties::ChangeOp(node, machine()->Int32SubWithOverflow());
252 : return Changed(node);
253 : }
254 3829 : break;
255 : }
256 : case IrOpcode::kInt32Div:
257 20127 : return ReduceInt32Div(node);
258 : case IrOpcode::kUint32Div:
259 19310 : return ReduceUint32Div(node);
260 : case IrOpcode::kInt32Mod:
261 30340 : return ReduceInt32Mod(node);
262 : case IrOpcode::kUint32Mod:
263 21060 : return ReduceUint32Mod(node);
264 : case IrOpcode::kInt32LessThan: {
265 263281 : Int32BinopMatcher m(node);
266 263289 : if (m.IsFoldable()) { // K < K => K
267 40714 : return ReplaceBool(m.left().Value() < m.right().Value());
268 : }
269 242973 : if (m.LeftEqualsRight()) return ReplaceBool(false); // x < x => false
270 244677 : if (m.left().IsWord32Or() && m.right().Is(0)) {
271 : // (x | K) < 0 => true or (K | x) < 0 => true iff K < 0
272 1680 : Int32BinopMatcher mleftmatcher(m.left().node());
273 3360 : if (mleftmatcher.left().IsNegative() ||
274 : mleftmatcher.right().IsNegative()) {
275 70 : return ReplaceBool(true);
276 : }
277 : }
278 242891 : break;
279 : }
280 : case IrOpcode::kInt32LessThanOrEqual: {
281 46711 : Int32BinopMatcher m(node);
282 46711 : if (m.IsFoldable()) { // K <= K => K
283 35291 : return ReplaceBool(m.left().Value() <= m.right().Value());
284 : }
285 29068 : if (m.LeftEqualsRight()) return ReplaceBool(true); // x <= x => true
286 29063 : break;
287 : }
288 : case IrOpcode::kUint32LessThan: {
289 188674 : Uint32BinopMatcher m(node);
290 210227 : if (m.left().Is(kMaxUInt32)) return ReplaceBool(false); // M < x => false
291 188361 : if (m.right().Is(0)) return ReplaceBool(false); // x < 0 => false
292 187926 : if (m.IsFoldable()) { // K < K => K
293 20393 : return ReplaceBool(m.left().Value() < m.right().Value());
294 : }
295 167533 : if (m.LeftEqualsRight()) return ReplaceBool(false); // x < x => false
296 167397 : if (m.left().IsWord32Sar() && m.right().HasValue()) {
297 318 : Int32BinopMatcher mleft(m.left().node());
298 318 : if (mleft.right().HasValue()) {
299 : // (x >> K) < C => x < (C << K)
300 : // when C < (M >> K)
301 318 : const uint32_t c = m.right().Value();
302 318 : const uint32_t k = mleft.right().Value() & 0x1F;
303 318 : if (c < static_cast<uint32_t>(kMaxInt >> k)) {
304 280 : node->ReplaceInput(0, mleft.left().node());
305 560 : node->ReplaceInput(1, Uint32Constant(c << k));
306 280 : return Changed(node);
307 : }
308 : // TODO(turbofan): else the comparison is always true.
309 : }
310 : }
311 167117 : break;
312 : }
313 : case IrOpcode::kUint32LessThanOrEqual: {
314 62095 : Uint32BinopMatcher m(node);
315 79281 : if (m.left().Is(0)) return ReplaceBool(true); // 0 <= x => true
316 61666 : if (m.right().Is(kMaxUInt32)) return ReplaceBool(true); // x <= M => true
317 61376 : if (m.IsFoldable()) { // K <= K => K
318 16461 : return ReplaceBool(m.left().Value() <= m.right().Value());
319 : }
320 44915 : if (m.LeftEqualsRight()) return ReplaceBool(true); // x <= x => true
321 44909 : break;
322 : }
323 : case IrOpcode::kFloat32Sub: {
324 66141 : Float32BinopMatcher m(node);
325 133432 : if (allow_signalling_nan_ && m.right().Is(0) &&
326 1150 : (copysign(1.0, m.right().Value()) > 0)) {
327 66136 : return Replace(m.left().node()); // x - 0 => x
328 : }
329 65566 : if (m.right().IsNaN()) { // x - NaN => NaN
330 : // Do some calculation to make a signalling NaN quiet.
331 1155 : return ReplaceFloat32(m.right().Value() - m.right().Value());
332 : }
333 64411 : if (m.left().IsNaN()) { // NaN - x => NaN
334 : // Do some calculation to make a signalling NaN quiet.
335 1125 : return ReplaceFloat32(m.left().Value() - m.left().Value());
336 : }
337 63286 : if (m.IsFoldable()) { // L - R => (L - R)
338 63280 : return ReplaceFloat32(m.left().Value() - m.right().Value());
339 : }
340 6 : if (allow_signalling_nan_ && m.left().IsMinusZero()) {
341 : // -0.0 - round_down(-0.0 - R) => round_up(R)
342 1 : if (machine()->Float32RoundUp().IsSupported() &&
343 : m.right().IsFloat32RoundDown()) {
344 0 : if (m.right().InputAt(0)->opcode() == IrOpcode::kFloat32Sub) {
345 0 : Float32BinopMatcher mright0(m.right().InputAt(0));
346 0 : if (mright0.left().IsMinusZero()) {
347 : return Replace(graph()->NewNode(machine()->Float32RoundUp().op(),
348 0 : mright0.right().node()));
349 : }
350 : }
351 : }
352 : // -0.0 - R => -R
353 1 : node->RemoveInput(0);
354 1 : NodeProperties::ChangeOp(node, machine()->Float32Neg());
355 : return Changed(node);
356 : }
357 5 : break;
358 : }
359 : case IrOpcode::kFloat64Add: {
360 146212 : Float64BinopMatcher m(node);
361 146221 : if (m.IsFoldable()) { // K + K => K
362 23950 : return ReplaceFloat64(m.left().Value() + m.right().Value());
363 : }
364 134246 : break;
365 : }
366 : case IrOpcode::kFloat64Sub: {
367 35962 : Float64BinopMatcher m(node);
368 72516 : if (allow_signalling_nan_ && m.right().Is(0) &&
369 592 : (Double(m.right().Value()).Sign() > 0)) {
370 21452 : return Replace(m.left().node()); // x - 0 => x
371 : }
372 35623 : if (m.right().IsNaN()) { // x - NaN => NaN
373 : // Do some calculation to make a signalling NaN quiet.
374 538 : return ReplaceFloat64(m.right().Value() - m.right().Value());
375 : }
376 35085 : if (m.left().IsNaN()) { // NaN - x => NaN
377 : // Do some calculation to make a signalling NaN quiet.
378 509 : return ReplaceFloat64(m.left().Value() - m.left().Value());
379 : }
380 34576 : if (m.IsFoldable()) { // L - R => (L - R)
381 11627 : return ReplaceFloat64(m.left().Value() - m.right().Value());
382 : }
383 22949 : if (allow_signalling_nan_ && m.left().IsMinusZero()) {
384 : // -0.0 - round_down(-0.0 - R) => round_up(R)
385 16876 : if (machine()->Float64RoundUp().IsSupported() &&
386 : m.right().IsFloat64RoundDown()) {
387 1260 : if (m.right().InputAt(0)->opcode() == IrOpcode::kFloat64Sub) {
388 0 : Float64BinopMatcher mright0(m.right().InputAt(0));
389 0 : if (mright0.left().IsMinusZero()) {
390 : return Replace(graph()->NewNode(machine()->Float64RoundUp().op(),
391 0 : mright0.right().node()));
392 : }
393 : }
394 : }
395 : // -0.0 - R => -R
396 8439 : node->RemoveInput(0);
397 8439 : NodeProperties::ChangeOp(node, machine()->Float64Neg());
398 : return Changed(node);
399 : }
400 14510 : break;
401 : }
402 : case IrOpcode::kFloat64Mul: {
403 23906 : Float64BinopMatcher m(node);
404 47812 : if (allow_signalling_nan_ && m.right().Is(1))
405 10481 : return Replace(m.left().node()); // x * 1.0 => x
406 23853 : if (m.right().Is(-1)) { // x * -1.0 => -0.0 - x
407 8618 : node->ReplaceInput(0, Float64Constant(-0.0));
408 8618 : node->ReplaceInput(1, m.left().node());
409 8618 : NodeProperties::ChangeOp(node, machine()->Float64Sub());
410 : return Changed(node);
411 : }
412 15235 : if (m.right().IsNaN()) { // x * NaN => NaN
413 : // Do some calculation to make a signalling NaN quiet.
414 33 : return ReplaceFloat64(m.right().Value() - m.right().Value());
415 : }
416 15202 : if (m.IsFoldable()) { // K * K => K
417 1642 : return ReplaceFloat64(m.left().Value() * m.right().Value());
418 : }
419 13560 : if (m.right().Is(2)) { // x * 2.0 => x + x
420 135 : node->ReplaceInput(1, m.left().node());
421 135 : NodeProperties::ChangeOp(node, machine()->Float64Add());
422 : return Changed(node);
423 : }
424 13425 : break;
425 : }
426 : case IrOpcode::kFloat64Div: {
427 29901 : Float64BinopMatcher m(node);
428 59802 : if (allow_signalling_nan_ && m.right().Is(1))
429 5885 : return Replace(m.left().node()); // x / 1.0 => x
430 : // TODO(ahaas): We could do x / 1.0 = x if we knew that x is not an sNaN.
431 29791 : if (m.right().IsNaN()) { // x / NaN => NaN
432 : // Do some calculation to make a signalling NaN quiet.
433 30 : return ReplaceFloat64(m.right().Value() - m.right().Value());
434 : }
435 29761 : if (m.left().IsNaN()) { // NaN / x => NaN
436 : // Do some calculation to make a signalling NaN quiet.
437 46 : return ReplaceFloat64(m.left().Value() - m.left().Value());
438 : }
439 29715 : if (m.IsFoldable()) { // K / K => K
440 : return ReplaceFloat64(
441 2877 : base::Divide(m.left().Value(), m.right().Value()));
442 : }
443 53676 : if (allow_signalling_nan_ && m.right().Is(-1)) { // x / -1.0 => -x
444 36 : node->RemoveInput(1);
445 36 : NodeProperties::ChangeOp(node, machine()->Float64Neg());
446 : return Changed(node);
447 : }
448 26802 : if (m.right().IsNormal() && m.right().IsPositiveOrNegativePowerOf2()) {
449 : // All reciprocals of non-denormal powers of two can be represented
450 : // exactly, so division by power of two can be reduced to
451 : // multiplication by reciprocal, with the same result.
452 5572 : node->ReplaceInput(1, Float64Constant(1.0 / m.right().Value()));
453 2786 : NodeProperties::ChangeOp(node, machine()->Float64Mul());
454 : return Changed(node);
455 : }
456 24016 : break;
457 : }
458 : case IrOpcode::kFloat64Mod: {
459 3141 : Float64BinopMatcher m(node);
460 3141 : if (m.right().Is(0)) { // x % 0 => NaN
461 1243 : return ReplaceFloat64(std::numeric_limits<double>::quiet_NaN());
462 : }
463 2989 : if (m.right().IsNaN()) { // x % NaN => NaN
464 : return Replace(m.right().node());
465 : }
466 2952 : if (m.left().IsNaN()) { // NaN % x => NaN
467 : return Replace(m.left().node());
468 : }
469 2925 : if (m.IsFoldable()) { // K % K => K
470 1027 : return ReplaceFloat64(Modulo(m.left().Value(), m.right().Value()));
471 : }
472 1898 : break;
473 : }
474 : case IrOpcode::kFloat64Acos: {
475 : Float64Matcher m(node->InputAt(0));
476 156 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::acos(m.Value()));
477 : break;
478 : }
479 : case IrOpcode::kFloat64Acosh: {
480 : Float64Matcher m(node->InputAt(0));
481 156 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::acosh(m.Value()));
482 : break;
483 : }
484 : case IrOpcode::kFloat64Asin: {
485 : Float64Matcher m(node->InputAt(0));
486 163 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::asin(m.Value()));
487 : break;
488 : }
489 : case IrOpcode::kFloat64Asinh: {
490 : Float64Matcher m(node->InputAt(0));
491 156 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::asinh(m.Value()));
492 : break;
493 : }
494 : case IrOpcode::kFloat64Atan: {
495 : Float64Matcher m(node->InputAt(0));
496 169 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::atan(m.Value()));
497 : break;
498 : }
499 : case IrOpcode::kFloat64Atanh: {
500 : Float64Matcher m(node->InputAt(0));
501 156 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::atanh(m.Value()));
502 : break;
503 : }
504 : case IrOpcode::kFloat64Atan2: {
505 10067 : Float64BinopMatcher m(node);
506 10067 : if (m.right().IsNaN()) {
507 10006 : return Replace(m.right().node());
508 : }
509 10066 : if (m.left().IsNaN()) {
510 : return Replace(m.left().node());
511 : }
512 10065 : if (m.IsFoldable()) {
513 : return ReplaceFloat64(
514 10004 : base::ieee754::atan2(m.left().Value(), m.right().Value()));
515 : }
516 61 : break;
517 : }
518 : case IrOpcode::kFloat64Cbrt: {
519 : Float64Matcher m(node->InputAt(0));
520 56 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::cbrt(m.Value()));
521 : break;
522 : }
523 : case IrOpcode::kFloat64Cos: {
524 : Float64Matcher m(node->InputAt(0));
525 309 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::cos(m.Value()));
526 : break;
527 : }
528 : case IrOpcode::kFloat64Cosh: {
529 : Float64Matcher m(node->InputAt(0));
530 170 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::cosh(m.Value()));
531 : break;
532 : }
533 : case IrOpcode::kFloat64Exp: {
534 : Float64Matcher m(node->InputAt(0));
535 224 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::exp(m.Value()));
536 : break;
537 : }
538 : case IrOpcode::kFloat64Expm1: {
539 : Float64Matcher m(node->InputAt(0));
540 77 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::expm1(m.Value()));
541 : break;
542 : }
543 : case IrOpcode::kFloat64Log: {
544 : Float64Matcher m(node->InputAt(0));
545 483 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::log(m.Value()));
546 : break;
547 : }
548 : case IrOpcode::kFloat64Log1p: {
549 : Float64Matcher m(node->InputAt(0));
550 156 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::log1p(m.Value()));
551 : break;
552 : }
553 : case IrOpcode::kFloat64Log10: {
554 : Float64Matcher m(node->InputAt(0));
555 56 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::log10(m.Value()));
556 : break;
557 : }
558 : case IrOpcode::kFloat64Log2: {
559 : Float64Matcher m(node->InputAt(0));
560 56 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::log2(m.Value()));
561 : break;
562 : }
563 : case IrOpcode::kFloat64Pow: {
564 11143 : Float64BinopMatcher m(node);
565 11143 : if (m.IsFoldable()) {
566 : return ReplaceFloat64(
567 21544 : base::ieee754::pow(m.left().Value(), m.right().Value()));
568 372 : } else if (m.right().Is(0.0)) { // x ** +-0.0 => 1.0
569 : return ReplaceFloat64(1.0);
570 370 : } else if (m.right().Is(-2.0)) { // x ** -2.0 => 1 / (x * x)
571 0 : node->ReplaceInput(0, Float64Constant(1.0));
572 0 : node->ReplaceInput(1, Float64Mul(m.left().node(), m.left().node()));
573 0 : NodeProperties::ChangeOp(node, machine()->Float64Div());
574 : return Changed(node);
575 370 : } else if (m.right().Is(2.0)) { // x ** 2.0 => x * x
576 0 : node->ReplaceInput(1, m.left().node());
577 0 : NodeProperties::ChangeOp(node, machine()->Float64Mul());
578 : return Changed(node);
579 370 : } else if (m.right().Is(-0.5)) {
580 : // x ** 0.5 => 1 / (if x <= -Infinity then Infinity else sqrt(0.0 + x))
581 0 : node->ReplaceInput(0, Float64Constant(1.0));
582 0 : node->ReplaceInput(1, Float64PowHalf(m.left().node()));
583 0 : NodeProperties::ChangeOp(node, machine()->Float64Div());
584 : return Changed(node);
585 370 : } else if (m.right().Is(0.5)) {
586 : // x ** 0.5 => if x <= -Infinity then Infinity else sqrt(0.0 + x)
587 0 : return Replace(Float64PowHalf(m.left().node()));
588 : }
589 370 : break;
590 : }
591 : case IrOpcode::kFloat64Sin: {
592 : Float64Matcher m(node->InputAt(0));
593 337 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::sin(m.Value()));
594 : break;
595 : }
596 : case IrOpcode::kFloat64Sinh: {
597 : Float64Matcher m(node->InputAt(0));
598 170 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::sinh(m.Value()));
599 : break;
600 : }
601 : case IrOpcode::kFloat64Tan: {
602 : Float64Matcher m(node->InputAt(0));
603 218 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::tan(m.Value()));
604 : break;
605 : }
606 : case IrOpcode::kFloat64Tanh: {
607 : Float64Matcher m(node->InputAt(0));
608 170 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::tanh(m.Value()));
609 : break;
610 : }
611 : case IrOpcode::kChangeFloat32ToFloat64: {
612 : Float32Matcher m(node->InputAt(0));
613 12545 : if (m.HasValue()) {
614 139 : if (!allow_signalling_nan_ && std::isnan(m.Value())) {
615 : // Do some calculation to make guarantee the value is a quiet NaN.
616 0 : return ReplaceFloat64(m.Value() + m.Value());
617 : }
618 139 : return ReplaceFloat64(m.Value());
619 : }
620 : break;
621 : }
622 : case IrOpcode::kChangeFloat64ToInt32: {
623 : Float64Matcher m(node->InputAt(0));
624 3812 : if (m.HasValue()) return ReplaceInt32(FastD2IChecked(m.Value()));
625 3670 : if (m.IsChangeInt32ToFloat64()) return Replace(m.node()->InputAt(0));
626 : break;
627 : }
628 : case IrOpcode::kChangeFloat64ToInt64: {
629 : Float64Matcher m(node->InputAt(0));
630 146 : if (m.HasValue()) return ReplaceInt64(static_cast<int64_t>(m.Value()));
631 42 : if (m.IsChangeInt64ToFloat64()) return Replace(m.node()->InputAt(0));
632 : break;
633 : }
634 : case IrOpcode::kChangeFloat64ToUint32: {
635 : Float64Matcher m(node->InputAt(0));
636 729 : if (m.HasValue()) return ReplaceInt32(FastD2UI(m.Value()));
637 615 : if (m.IsChangeUint32ToFloat64()) return Replace(m.node()->InputAt(0));
638 : break;
639 : }
640 : case IrOpcode::kChangeInt32ToFloat64: {
641 : Int32Matcher m(node->InputAt(0));
642 246924 : if (m.HasValue()) return ReplaceFloat64(FastI2D(m.Value()));
643 : break;
644 : }
645 : case IrOpcode::kChangeInt32ToInt64: {
646 : Int32Matcher m(node->InputAt(0));
647 324583 : if (m.HasValue()) return ReplaceInt64(m.Value());
648 : break;
649 : }
650 : case IrOpcode::kChangeInt64ToFloat64: {
651 : Int64Matcher m(node->InputAt(0));
652 845 : if (m.HasValue()) return ReplaceFloat64(static_cast<double>(m.Value()));
653 349 : if (m.IsChangeFloat64ToInt64()) return Replace(m.node()->InputAt(0));
654 : break;
655 : }
656 : case IrOpcode::kChangeUint32ToFloat64: {
657 : Uint32Matcher m(node->InputAt(0));
658 6451 : if (m.HasValue()) return ReplaceFloat64(FastUI2D(m.Value()));
659 : break;
660 : }
661 : case IrOpcode::kChangeUint32ToUint64: {
662 : Uint32Matcher m(node->InputAt(0));
663 287659 : if (m.HasValue()) return ReplaceInt64(static_cast<uint64_t>(m.Value()));
664 : break;
665 : }
666 : case IrOpcode::kTruncateFloat64ToWord32: {
667 : Float64Matcher m(node->InputAt(0));
668 24406 : if (m.HasValue()) return ReplaceInt32(DoubleToInt32(m.Value()));
669 21119 : if (m.IsChangeInt32ToFloat64()) return Replace(m.node()->InputAt(0));
670 : return NoChange();
671 : }
672 : case IrOpcode::kTruncateInt64ToInt32: {
673 : Int64Matcher m(node->InputAt(0));
674 298034 : if (m.HasValue()) return ReplaceInt32(static_cast<int32_t>(m.Value()));
675 286810 : if (m.IsChangeInt32ToInt64()) return Replace(m.node()->InputAt(0));
676 : break;
677 : }
678 : case IrOpcode::kTruncateFloat64ToFloat32: {
679 : Float64Matcher m(node->InputAt(0));
680 8154 : if (m.HasValue()) {
681 673 : if (!allow_signalling_nan_ && std::isnan(m.Value())) {
682 : // Do some calculation to make guarantee the value is a quiet NaN.
683 0 : return ReplaceFloat32(DoubleToFloat32(m.Value() + m.Value()));
684 : }
685 : return ReplaceFloat32(DoubleToFloat32(m.Value()));
686 : }
687 7481 : if (allow_signalling_nan_ && m.IsChangeFloat32ToFloat64())
688 : return Replace(m.node()->InputAt(0));
689 : break;
690 : }
691 : case IrOpcode::kRoundFloat64ToInt32: {
692 : Float64Matcher m(node->InputAt(0));
693 70361 : if (m.HasValue()) {
694 281 : return ReplaceInt32(DoubleToInt32(m.Value()));
695 : }
696 70080 : if (m.IsChangeInt32ToFloat64()) return Replace(m.node()->InputAt(0));
697 : break;
698 : }
699 : case IrOpcode::kFloat64InsertLowWord32:
700 4856 : return ReduceFloat64InsertLowWord32(node);
701 : case IrOpcode::kFloat64InsertHighWord32:
702 4856 : return ReduceFloat64InsertHighWord32(node);
703 : case IrOpcode::kStore:
704 : case IrOpcode::kUnalignedStore:
705 3314253 : return ReduceStore(node);
706 : case IrOpcode::kFloat64Equal:
707 : case IrOpcode::kFloat64LessThan:
708 : case IrOpcode::kFloat64LessThanOrEqual:
709 227704 : return ReduceFloat64Compare(node);
710 : case IrOpcode::kFloat64RoundDown:
711 52000 : return ReduceFloat64RoundDown(node);
712 : case IrOpcode::kBitcastTaggedToWord: {
713 : NodeMatcher m(node->InputAt(0));
714 1173091 : if (m.IsBitcastWordToTaggedSigned()) {
715 : RelaxEffectsAndControls(node);
716 : return Replace(m.InputAt(0));
717 : }
718 : break;
719 : }
720 : default:
721 : break;
722 : }
723 : return NoChange();
724 : }
725 :
726 495638 : Reduction MachineOperatorReducer::ReduceInt32Add(Node* node) {
727 : DCHECK_EQ(IrOpcode::kInt32Add, node->opcode());
728 495638 : Int32BinopMatcher m(node);
729 495643 : if (m.right().Is(0)) return Replace(m.left().node()); // x + 0 => x
730 471676 : if (m.IsFoldable()) { // K + K => K
731 : return ReplaceInt32(
732 38764 : base::AddWithWraparound(m.left().Value(), m.right().Value()));
733 : }
734 432912 : if (m.left().IsInt32Sub()) {
735 1451 : Int32BinopMatcher mleft(m.left().node());
736 1451 : if (mleft.left().Is(0)) { // (0 - x) + y => y - x
737 122 : node->ReplaceInput(0, m.right().node());
738 122 : node->ReplaceInput(1, mleft.right().node());
739 122 : NodeProperties::ChangeOp(node, machine()->Int32Sub());
740 122 : Reduction const reduction = ReduceInt32Sub(node);
741 122 : return reduction.Changed() ? reduction : Changed(node);
742 : }
743 : }
744 432790 : if (m.right().IsInt32Sub()) {
745 453 : Int32BinopMatcher mright(m.right().node());
746 453 : if (mright.left().Is(0)) { // y + (0 - x) => y - x
747 42 : node->ReplaceInput(1, mright.right().node());
748 42 : NodeProperties::ChangeOp(node, machine()->Int32Sub());
749 42 : Reduction const reduction = ReduceInt32Sub(node);
750 42 : return reduction.Changed() ? reduction : Changed(node);
751 : }
752 : }
753 : return NoChange();
754 : }
755 :
756 1910294 : Reduction MachineOperatorReducer::ReduceInt64Add(Node* node) {
757 : DCHECK_EQ(IrOpcode::kInt64Add, node->opcode());
758 1910294 : Int64BinopMatcher m(node);
759 1910296 : if (m.right().Is(0)) return Replace(m.left().node()); // x + 0 => 0
760 1899581 : if (m.IsFoldable()) {
761 : return ReplaceInt64(
762 77129 : base::AddWithWraparound(m.left().Value(), m.right().Value()));
763 : }
764 : return NoChange();
765 : }
766 :
767 55542 : Reduction MachineOperatorReducer::ReduceInt32Sub(Node* node) {
768 : DCHECK_EQ(IrOpcode::kInt32Sub, node->opcode());
769 55542 : Int32BinopMatcher m(node);
770 55542 : if (m.right().Is(0)) return Replace(m.left().node()); // x - 0 => x
771 54898 : if (m.IsFoldable()) { // K - K => K
772 : return ReplaceInt32(
773 19352 : base::SubWithWraparound(m.left().Value(), m.right().Value()));
774 : }
775 35546 : if (m.LeftEqualsRight()) return ReplaceInt32(0); // x - x => 0
776 35546 : if (m.right().HasValue()) { // x - K => x + -K
777 : node->ReplaceInput(
778 27646 : 1, Int32Constant(base::NegateWithWraparound(m.right().Value())));
779 13823 : NodeProperties::ChangeOp(node, machine()->Int32Add());
780 13823 : Reduction const reduction = ReduceInt32Add(node);
781 13823 : return reduction.Changed() ? reduction : Changed(node);
782 : }
783 : return NoChange();
784 : }
785 :
786 316392 : Reduction MachineOperatorReducer::ReduceInt64Sub(Node* node) {
787 : DCHECK_EQ(IrOpcode::kInt64Sub, node->opcode());
788 316392 : Int64BinopMatcher m(node);
789 316391 : if (m.right().Is(0)) return Replace(m.left().node()); // x - 0 => x
790 311832 : if (m.IsFoldable()) { // K - K => K
791 : return ReplaceInt64(
792 34449 : base::SubWithWraparound(m.left().Value(), m.right().Value()));
793 : }
794 277383 : if (m.LeftEqualsRight()) return Replace(Int64Constant(0)); // x - x => 0
795 277375 : if (m.right().HasValue()) { // x - K => x + -K
796 : node->ReplaceInput(
797 524268 : 1, Int64Constant(base::NegateWithWraparound(m.right().Value())));
798 262135 : NodeProperties::ChangeOp(node, machine()->Int64Add());
799 262135 : Reduction const reduction = ReduceInt64Add(node);
800 262135 : return reduction.Changed() ? reduction : Changed(node);
801 : }
802 : return NoChange();
803 : }
804 :
805 20127 : Reduction MachineOperatorReducer::ReduceInt32Div(Node* node) {
806 20127 : Int32BinopMatcher m(node);
807 20127 : if (m.left().Is(0)) return Replace(m.left().node()); // 0 / x => 0
808 19836 : if (m.right().Is(0)) return Replace(m.right().node()); // x / 0 => 0
809 19835 : if (m.right().Is(1)) return Replace(m.left().node()); // x / 1 => x
810 19516 : if (m.IsFoldable()) { // K / K => K
811 : return ReplaceInt32(
812 16014 : base::bits::SignedDiv32(m.left().Value(), m.right().Value()));
813 : }
814 3502 : if (m.LeftEqualsRight()) { // x / x => x != 0
815 : Node* const zero = Int32Constant(0);
816 5 : return Replace(Word32Equal(Word32Equal(m.left().node(), zero), zero));
817 : }
818 3497 : if (m.right().Is(-1)) { // x / -1 => 0 - x
819 31 : node->ReplaceInput(0, Int32Constant(0));
820 31 : node->ReplaceInput(1, m.left().node());
821 31 : node->TrimInputCount(2);
822 31 : NodeProperties::ChangeOp(node, machine()->Int32Sub());
823 : return Changed(node);
824 : }
825 3466 : if (m.right().HasValue()) {
826 2523 : int32_t const divisor = m.right().Value();
827 : Node* const dividend = m.left().node();
828 : Node* quotient = dividend;
829 2523 : if (base::bits::IsPowerOfTwo(Abs(divisor))) {
830 673 : uint32_t const shift = WhichPowerOf2(Abs(divisor));
831 : DCHECK_NE(0u, shift);
832 673 : if (shift > 1) {
833 573 : quotient = Word32Sar(quotient, 31);
834 : }
835 673 : quotient = Int32Add(Word32Shr(quotient, 32u - shift), dividend);
836 673 : quotient = Word32Sar(quotient, shift);
837 : } else {
838 1850 : quotient = Int32Div(quotient, Abs(divisor));
839 : }
840 2523 : if (divisor < 0) {
841 1138 : node->ReplaceInput(0, Int32Constant(0));
842 1138 : node->ReplaceInput(1, quotient);
843 1138 : node->TrimInputCount(2);
844 1138 : NodeProperties::ChangeOp(node, machine()->Int32Sub());
845 : return Changed(node);
846 : }
847 : return Replace(quotient);
848 : }
849 : return NoChange();
850 : }
851 :
852 :
853 19310 : Reduction MachineOperatorReducer::ReduceUint32Div(Node* node) {
854 19310 : Uint32BinopMatcher m(node);
855 19310 : if (m.left().Is(0)) return Replace(m.left().node()); // 0 / x => 0
856 18968 : if (m.right().Is(0)) return Replace(m.right().node()); // x / 0 => 0
857 18920 : if (m.right().Is(1)) return Replace(m.left().node()); // x / 1 => x
858 18577 : if (m.IsFoldable()) { // K / K => K
859 : return ReplaceUint32(
860 18154 : base::bits::UnsignedDiv32(m.left().Value(), m.right().Value()));
861 : }
862 423 : if (m.LeftEqualsRight()) { // x / x => x != 0
863 : Node* const zero = Int32Constant(0);
864 1 : return Replace(Word32Equal(Word32Equal(m.left().node(), zero), zero));
865 : }
866 422 : if (m.right().HasValue()) {
867 : Node* const dividend = m.left().node();
868 273 : uint32_t const divisor = m.right().Value();
869 273 : if (base::bits::IsPowerOfTwo(divisor)) { // x / 2^n => x >> n
870 432 : node->ReplaceInput(1, Uint32Constant(WhichPowerOf2(m.right().Value())));
871 216 : node->TrimInputCount(2);
872 216 : NodeProperties::ChangeOp(node, machine()->Word32Shr());
873 : return Changed(node);
874 : } else {
875 57 : return Replace(Uint32Div(dividend, divisor));
876 : }
877 : }
878 : return NoChange();
879 : }
880 :
881 :
882 30340 : Reduction MachineOperatorReducer::ReduceInt32Mod(Node* node) {
883 30340 : Int32BinopMatcher m(node);
884 30340 : if (m.left().Is(0)) return Replace(m.left().node()); // 0 % x => 0
885 29936 : if (m.right().Is(0)) return Replace(m.right().node()); // x % 0 => 0
886 29836 : if (m.right().Is(1)) return ReplaceInt32(0); // x % 1 => 0
887 29525 : if (m.right().Is(-1)) return ReplaceInt32(0); // x % -1 => 0
888 29239 : if (m.LeftEqualsRight()) return ReplaceInt32(0); // x % x => 0
889 29230 : if (m.IsFoldable()) { // K % K => K
890 : return ReplaceInt32(
891 25563 : base::bits::SignedMod32(m.left().Value(), m.right().Value()));
892 : }
893 3667 : if (m.right().HasValue()) {
894 : Node* const dividend = m.left().node();
895 2562 : uint32_t const divisor = Abs(m.right().Value());
896 2562 : if (base::bits::IsPowerOfTwo(divisor)) {
897 696 : uint32_t const mask = divisor - 1;
898 : Node* const zero = Int32Constant(0);
899 : Diamond d(graph(), common(),
900 : graph()->NewNode(machine()->Int32LessThan(), dividend, zero),
901 1392 : BranchHint::kFalse);
902 : return Replace(
903 : d.Phi(MachineRepresentation::kWord32,
904 : Int32Sub(zero, Word32And(Int32Sub(zero, dividend), mask)),
905 696 : Word32And(dividend, mask)));
906 : } else {
907 1866 : Node* quotient = Int32Div(dividend, divisor);
908 : DCHECK_EQ(dividend, node->InputAt(0));
909 1866 : node->ReplaceInput(1, Int32Mul(quotient, Int32Constant(divisor)));
910 1866 : node->TrimInputCount(2);
911 1866 : NodeProperties::ChangeOp(node, machine()->Int32Sub());
912 : }
913 : return Changed(node);
914 : }
915 : return NoChange();
916 : }
917 :
918 :
919 21060 : Reduction MachineOperatorReducer::ReduceUint32Mod(Node* node) {
920 21060 : Uint32BinopMatcher m(node);
921 21060 : if (m.left().Is(0)) return Replace(m.left().node()); // 0 % x => 0
922 20676 : if (m.right().Is(0)) return Replace(m.right().node()); // x % 0 => 0
923 20628 : if (m.right().Is(1)) return ReplaceUint32(0); // x % 1 => 0
924 20285 : if (m.LeftEqualsRight()) return ReplaceInt32(0); // x % x => 0
925 20283 : if (m.IsFoldable()) { // K % K => K
926 : return ReplaceUint32(
927 18200 : base::bits::UnsignedMod32(m.left().Value(), m.right().Value()));
928 : }
929 2083 : if (m.right().HasValue()) {
930 : Node* const dividend = m.left().node();
931 1612 : uint32_t const divisor = m.right().Value();
932 1612 : if (base::bits::IsPowerOfTwo(divisor)) { // x % 2^n => x & 2^n-1
933 956 : node->ReplaceInput(1, Uint32Constant(m.right().Value() - 1));
934 478 : node->TrimInputCount(2);
935 478 : NodeProperties::ChangeOp(node, machine()->Word32And());
936 : } else {
937 1134 : Node* quotient = Uint32Div(dividend, divisor);
938 : DCHECK_EQ(dividend, node->InputAt(0));
939 1134 : node->ReplaceInput(1, Int32Mul(quotient, Uint32Constant(divisor)));
940 1134 : node->TrimInputCount(2);
941 1134 : NodeProperties::ChangeOp(node, machine()->Int32Sub());
942 : }
943 : return Changed(node);
944 : }
945 : return NoChange();
946 : }
947 :
948 :
949 3314250 : Reduction MachineOperatorReducer::ReduceStore(Node* node) {
950 : NodeMatcher nm(node);
951 : MachineRepresentation rep;
952 : int value_input;
953 3314250 : if (nm.IsStore()) {
954 3314250 : rep = StoreRepresentationOf(node->op()).representation();
955 : value_input = 2;
956 : } else {
957 : DCHECK(nm.IsUnalignedStore());
958 0 : rep = UnalignedStoreRepresentationOf(node->op());
959 : value_input = 2;
960 : }
961 :
962 3314250 : Node* const value = node->InputAt(value_input);
963 :
964 3314250 : switch (value->opcode()) {
965 : case IrOpcode::kWord32And: {
966 7148 : Uint32BinopMatcher m(value);
967 19400 : if (m.right().HasValue() && ((rep == MachineRepresentation::kWord8 &&
968 6941 : (m.right().Value() & 0xFF) == 0xFF) ||
969 1308 : (rep == MachineRepresentation::kWord16 &&
970 1308 : (m.right().Value() & 0xFFFF) == 0xFFFF))) {
971 6176 : node->ReplaceInput(value_input, m.left().node());
972 6176 : return Changed(node);
973 : }
974 972 : break;
975 : }
976 : case IrOpcode::kWord32Sar: {
977 377 : Int32BinopMatcher m(value);
978 883 : if (m.left().IsWord32Shl() && ((rep == MachineRepresentation::kWord8 &&
979 201 : m.right().IsInRange(1, 24)) ||
980 193 : (rep == MachineRepresentation::kWord16 &&
981 : m.right().IsInRange(1, 16)))) {
982 322 : Int32BinopMatcher mleft(m.left().node());
983 322 : if (mleft.right().Is(m.right().Value())) {
984 322 : node->ReplaceInput(value_input, mleft.left().node());
985 322 : return Changed(node);
986 : }
987 : }
988 55 : break;
989 : }
990 : default:
991 : break;
992 : }
993 : return NoChange();
994 : }
995 :
996 :
997 249503 : Reduction MachineOperatorReducer::ReduceProjection(size_t index, Node* node) {
998 249503 : switch (node->opcode()) {
999 : case IrOpcode::kInt32AddWithOverflow: {
1000 : DCHECK(index == 0 || index == 1);
1001 147376 : Int32BinopMatcher m(node);
1002 147387 : if (m.IsFoldable()) {
1003 : int32_t val;
1004 : bool ovf = base::bits::SignedAddOverflow32(m.left().Value(),
1005 20004 : m.right().Value(), &val);
1006 20004 : return ReplaceInt32(index == 0 ? val : ovf);
1007 : }
1008 127383 : if (m.right().Is(0)) {
1009 32 : return Replace(index == 0 ? m.left().node() : m.right().node());
1010 : }
1011 127351 : break;
1012 : }
1013 : case IrOpcode::kInt32SubWithOverflow: {
1014 : DCHECK(index == 0 || index == 1);
1015 44824 : Int32BinopMatcher m(node);
1016 44824 : if (m.IsFoldable()) {
1017 : int32_t val;
1018 : bool ovf = base::bits::SignedSubOverflow32(m.left().Value(),
1019 20056 : m.right().Value(), &val);
1020 20056 : return ReplaceInt32(index == 0 ? val : ovf);
1021 : }
1022 24768 : if (m.right().Is(0)) {
1023 2 : return Replace(index == 0 ? m.left().node() : m.right().node());
1024 : }
1025 24766 : break;
1026 : }
1027 : case IrOpcode::kInt32MulWithOverflow: {
1028 : DCHECK(index == 0 || index == 1);
1029 27490 : Int32BinopMatcher m(node);
1030 27490 : if (m.IsFoldable()) {
1031 : int32_t val;
1032 : bool ovf = base::bits::SignedMulOverflow32(m.left().Value(),
1033 20310 : m.right().Value(), &val);
1034 20310 : return ReplaceInt32(index == 0 ? val : ovf);
1035 : }
1036 7180 : if (m.right().Is(0)) {
1037 : return Replace(m.right().node());
1038 : }
1039 7096 : if (m.right().Is(1)) {
1040 72 : return index == 0 ? Replace(m.left().node()) : ReplaceInt32(0);
1041 : }
1042 7024 : break;
1043 : }
1044 : default:
1045 : break;
1046 : }
1047 : return NoChange();
1048 : }
1049 :
1050 :
1051 104857 : Reduction MachineOperatorReducer::ReduceWord32Shifts(Node* node) {
1052 : DCHECK((node->opcode() == IrOpcode::kWord32Shl) ||
1053 : (node->opcode() == IrOpcode::kWord32Shr) ||
1054 : (node->opcode() == IrOpcode::kWord32Sar));
1055 104857 : if (machine()->Word32ShiftIsSafe()) {
1056 : // Remove the explicit 'and' with 0x1F if the shift provided by the machine
1057 : // instruction matches that required by JavaScript.
1058 104542 : Int32BinopMatcher m(node);
1059 104542 : if (m.right().IsWord32And()) {
1060 1994 : Int32BinopMatcher mright(m.right().node());
1061 1994 : if (mright.right().Is(0x1F)) {
1062 995 : node->ReplaceInput(1, mright.left().node());
1063 995 : return Changed(node);
1064 : }
1065 : }
1066 : }
1067 : return NoChange();
1068 : }
1069 :
1070 :
1071 45116 : Reduction MachineOperatorReducer::ReduceWord32Shl(Node* node) {
1072 : DCHECK_EQ(IrOpcode::kWord32Shl, node->opcode());
1073 45116 : Int32BinopMatcher m(node);
1074 45116 : if (m.right().Is(0)) return Replace(m.left().node()); // x << 0 => x
1075 44416 : if (m.IsFoldable()) { // K << K => K
1076 : return ReplaceInt32(
1077 14151 : base::ShlWithWraparound(m.left().Value(), m.right().Value()));
1078 : }
1079 30265 : if (m.right().IsInRange(1, 31)) {
1080 : // (x >>> K) << K => x & ~(2^K - 1)
1081 : // (x >> K) << K => x & ~(2^K - 1)
1082 26996 : if (m.left().IsWord32Sar() || m.left().IsWord32Shr()) {
1083 3993 : Int32BinopMatcher mleft(m.left().node());
1084 3993 : if (mleft.right().Is(m.right().Value())) {
1085 3057 : node->ReplaceInput(0, mleft.left().node());
1086 : node->ReplaceInput(1,
1087 6114 : Uint32Constant(~((1U << m.right().Value()) - 1U)));
1088 3057 : NodeProperties::ChangeOp(node, machine()->Word32And());
1089 3057 : Reduction reduction = ReduceWord32And(node);
1090 3057 : return reduction.Changed() ? reduction : Changed(node);
1091 : }
1092 : }
1093 : }
1094 27208 : return ReduceWord32Shifts(node);
1095 : }
1096 :
1097 613506 : Reduction MachineOperatorReducer::ReduceWord64Shl(Node* node) {
1098 : DCHECK_EQ(IrOpcode::kWord64Shl, node->opcode());
1099 613506 : Int64BinopMatcher m(node);
1100 613508 : if (m.right().Is(0)) return Replace(m.left().node()); // x << 0 => x
1101 613098 : if (m.IsFoldable()) { // K << K => K
1102 : return ReplaceInt64(
1103 84814 : base::ShlWithWraparound(m.left().Value(), m.right().Value()));
1104 : }
1105 : return NoChange();
1106 : }
1107 :
1108 80829 : Reduction MachineOperatorReducer::ReduceWord32Shr(Node* node) {
1109 80829 : Uint32BinopMatcher m(node);
1110 80829 : if (m.right().Is(0)) return Replace(m.left().node()); // x >>> 0 => x
1111 67858 : if (m.IsFoldable()) { // K >>> K => K
1112 9987 : return ReplaceInt32(m.left().Value() >> (m.right().Value() & 31));
1113 : }
1114 57871 : if (m.left().IsWord32And() && m.right().HasValue()) {
1115 28563 : Uint32BinopMatcher mleft(m.left().node());
1116 28563 : if (mleft.right().HasValue()) {
1117 28560 : uint32_t shift = m.right().Value() & 31;
1118 28560 : uint32_t mask = mleft.right().Value();
1119 28560 : if ((mask >> shift) == 0) {
1120 : // (m >>> s) == 0 implies ((x & m) >>> s) == 0
1121 31 : return ReplaceInt32(0);
1122 : }
1123 : }
1124 : }
1125 57840 : return ReduceWord32Shifts(node);
1126 : }
1127 :
1128 49142 : Reduction MachineOperatorReducer::ReduceWord64Shr(Node* node) {
1129 : DCHECK_EQ(IrOpcode::kWord64Shr, node->opcode());
1130 49142 : Uint64BinopMatcher m(node);
1131 49142 : if (m.right().Is(0)) return Replace(m.left().node()); // x >>> 0 => x
1132 48732 : if (m.IsFoldable()) { // K >> K => K
1133 25515 : return ReplaceInt64(m.left().Value() >> (m.right().Value() & 63));
1134 : }
1135 : return NoChange();
1136 : }
1137 :
1138 30895 : Reduction MachineOperatorReducer::ReduceWord32Sar(Node* node) {
1139 30895 : Int32BinopMatcher m(node);
1140 30895 : if (m.right().Is(0)) return Replace(m.left().node()); // x >> 0 => x
1141 30092 : if (m.IsFoldable()) { // K >> K => K
1142 10232 : return ReplaceInt32(m.left().Value() >> (m.right().Value() & 31));
1143 : }
1144 19860 : if (m.left().IsWord32Shl()) {
1145 1263 : Int32BinopMatcher mleft(m.left().node());
1146 1263 : if (mleft.left().IsComparison()) {
1147 98 : if (m.right().Is(31) && mleft.right().Is(31)) {
1148 : // Comparison << 31 >> 31 => 0 - Comparison
1149 49 : node->ReplaceInput(0, Int32Constant(0));
1150 49 : node->ReplaceInput(1, mleft.left().node());
1151 49 : NodeProperties::ChangeOp(node, machine()->Int32Sub());
1152 49 : Reduction const reduction = ReduceInt32Sub(node);
1153 49 : return reduction.Changed() ? reduction : Changed(node);
1154 : }
1155 1214 : } else if (mleft.left().IsLoad()) {
1156 : LoadRepresentation const rep =
1157 2 : LoadRepresentationOf(mleft.left().node()->op());
1158 4 : if (m.right().Is(24) && mleft.right().Is(24) &&
1159 : rep == MachineType::Int8()) {
1160 : // Load[kMachInt8] << 24 >> 24 => Load[kMachInt8]
1161 : return Replace(mleft.left().node());
1162 : }
1163 3 : if (m.right().Is(16) && mleft.right().Is(16) &&
1164 : rep == MachineType::Int16()) {
1165 : // Load[kMachInt16] << 16 >> 16 => Load[kMachInt8]
1166 : return Replace(mleft.left().node());
1167 : }
1168 : }
1169 : }
1170 19809 : return ReduceWord32Shifts(node);
1171 : }
1172 :
1173 338151 : Reduction MachineOperatorReducer::ReduceWord64Sar(Node* node) {
1174 338151 : Int64BinopMatcher m(node);
1175 338153 : if (m.right().Is(0)) return Replace(m.left().node()); // x >> 0 => x
1176 337743 : if (m.IsFoldable()) {
1177 34160 : return ReplaceInt64(m.left().Value() >> (m.right().Value() & 63));
1178 : }
1179 : return NoChange();
1180 : }
1181 :
1182 631438 : Reduction MachineOperatorReducer::ReduceWord32And(Node* node) {
1183 : DCHECK_EQ(IrOpcode::kWord32And, node->opcode());
1184 631438 : Int32BinopMatcher m(node);
1185 631438 : if (m.right().Is(0)) return Replace(m.right().node()); // x & 0 => 0
1186 629539 : if (m.right().Is(-1)) return Replace(m.left().node()); // x & -1 => x
1187 630227 : if (m.left().IsComparison() && m.right().Is(1)) { // CMP & 1 => CMP
1188 : return Replace(m.left().node());
1189 : }
1190 628882 : if (m.IsFoldable()) { // K & K => K
1191 27790 : return ReplaceInt32(m.left().Value() & m.right().Value());
1192 : }
1193 601092 : if (m.LeftEqualsRight()) return Replace(m.left().node()); // x & x => x
1194 600991 : if (m.left().IsWord32And() && m.right().HasValue()) {
1195 25184 : Int32BinopMatcher mleft(m.left().node());
1196 25184 : if (mleft.right().HasValue()) { // (x & K) & K => x & K
1197 19719 : node->ReplaceInput(0, mleft.left().node());
1198 : node->ReplaceInput(
1199 39438 : 1, Int32Constant(m.right().Value() & mleft.right().Value()));
1200 19719 : Reduction const reduction = ReduceWord32And(node);
1201 19719 : return reduction.Changed() ? reduction : Changed(node);
1202 : }
1203 : }
1204 581272 : if (m.right().IsNegativePowerOf2()) {
1205 253986 : int32_t const mask = m.right().Value();
1206 : int32_t const neg_mask = base::NegateWithWraparound(mask);
1207 253986 : if (m.left().IsWord32Shl()) {
1208 2142 : Uint32BinopMatcher mleft(m.left().node());
1209 4284 : if (mleft.right().HasValue() &&
1210 2142 : (mleft.right().Value() & 0x1F) >=
1211 : base::bits::CountTrailingZeros(mask)) {
1212 : // (x << L) & (-1 << K) => x << L iff L >= K
1213 2140 : return Replace(mleft.node());
1214 : }
1215 251844 : } else if (m.left().IsInt32Add()) {
1216 94802 : Int32BinopMatcher mleft(m.left().node());
1217 169539 : if (mleft.right().HasValue() &&
1218 74737 : (mleft.right().Value() & mask) == mleft.right().Value()) {
1219 : // (x + (K << L)) & (-1 << L) => (x & (-1 << L)) + (K << L)
1220 74582 : node->ReplaceInput(0, Word32And(mleft.left().node(), m.right().node()));
1221 74582 : node->ReplaceInput(1, mleft.right().node());
1222 74582 : NodeProperties::ChangeOp(node, machine()->Int32Add());
1223 74582 : Reduction const reduction = ReduceInt32Add(node);
1224 74582 : return reduction.Changed() ? reduction : Changed(node);
1225 : }
1226 20220 : if (mleft.left().IsInt32Mul()) {
1227 2924 : Int32BinopMatcher mleftleft(mleft.left().node());
1228 2924 : if (mleftleft.right().IsMultipleOf(neg_mask)) {
1229 : // (y * (K << L) + x) & (-1 << L) => (x & (-1 << L)) + y * (K << L)
1230 : node->ReplaceInput(0,
1231 2923 : Word32And(mleft.right().node(), m.right().node()));
1232 2923 : node->ReplaceInput(1, mleftleft.node());
1233 2923 : NodeProperties::ChangeOp(node, machine()->Int32Add());
1234 2923 : Reduction const reduction = ReduceInt32Add(node);
1235 2923 : return reduction.Changed() ? reduction : Changed(node);
1236 : }
1237 : }
1238 17297 : if (mleft.right().IsInt32Mul()) {
1239 7153 : Int32BinopMatcher mleftright(mleft.right().node());
1240 7153 : if (mleftright.right().IsMultipleOf(neg_mask)) {
1241 : // (x + y * (K << L)) & (-1 << L) => (x & (-1 << L)) + y * (K << L)
1242 : node->ReplaceInput(0,
1243 7143 : Word32And(mleft.left().node(), m.right().node()));
1244 7143 : node->ReplaceInput(1, mleftright.node());
1245 7143 : NodeProperties::ChangeOp(node, machine()->Int32Add());
1246 7143 : Reduction const reduction = ReduceInt32Add(node);
1247 7143 : return reduction.Changed() ? reduction : Changed(node);
1248 : }
1249 : }
1250 10154 : if (mleft.left().IsWord32Shl()) {
1251 36 : Int32BinopMatcher mleftleft(mleft.left().node());
1252 72 : if (mleftleft.right().Is(base::bits::CountTrailingZeros(mask))) {
1253 : // (y << L + x) & (-1 << L) => (x & (-1 << L)) + y << L
1254 : node->ReplaceInput(0,
1255 31 : Word32And(mleft.right().node(), m.right().node()));
1256 31 : node->ReplaceInput(1, mleftleft.node());
1257 31 : NodeProperties::ChangeOp(node, machine()->Int32Add());
1258 31 : Reduction const reduction = ReduceInt32Add(node);
1259 31 : return reduction.Changed() ? reduction : Changed(node);
1260 : }
1261 : }
1262 10123 : if (mleft.right().IsWord32Shl()) {
1263 6360 : Int32BinopMatcher mleftright(mleft.right().node());
1264 12720 : if (mleftright.right().Is(base::bits::CountTrailingZeros(mask))) {
1265 : // (x + y << L) & (-1 << L) => (x & (-1 << L)) + y << L
1266 : node->ReplaceInput(0,
1267 2425 : Word32And(mleft.left().node(), m.right().node()));
1268 2425 : node->ReplaceInput(1, mleftright.node());
1269 2425 : NodeProperties::ChangeOp(node, machine()->Int32Add());
1270 2425 : Reduction const reduction = ReduceInt32Add(node);
1271 2425 : return reduction.Changed() ? reduction : Changed(node);
1272 : }
1273 : }
1274 157042 : } else if (m.left().IsInt32Mul()) {
1275 5892 : Int32BinopMatcher mleft(m.left().node());
1276 5892 : if (mleft.right().IsMultipleOf(neg_mask)) {
1277 : // (x * (K << L)) & (-1 << L) => x * (K << L)
1278 5892 : return Replace(mleft.node());
1279 : }
1280 : }
1281 : }
1282 : return NoChange();
1283 : }
1284 :
1285 49293 : Reduction MachineOperatorReducer::TryMatchWord32Ror(Node* node) {
1286 : DCHECK(IrOpcode::kWord32Or == node->opcode() ||
1287 : IrOpcode::kWord32Xor == node->opcode());
1288 49293 : Int32BinopMatcher m(node);
1289 : Node* shl = nullptr;
1290 : Node* shr = nullptr;
1291 : // Recognize rotation, we are matching:
1292 : // * x << y | x >>> (32 - y) => x ror (32 - y), i.e x rol y
1293 : // * x << (32 - y) | x >>> y => x ror y
1294 : // * x << y ^ x >>> (32 - y) => x ror (32 - y), i.e. x rol y
1295 : // * x << (32 - y) ^ x >>> y => x ror y
1296 : // as well as their commuted form.
1297 54800 : if (m.left().IsWord32Shl() && m.right().IsWord32Shr()) {
1298 : shl = m.left().node();
1299 : shr = m.right().node();
1300 48826 : } else if (m.left().IsWord32Shr() && m.right().IsWord32Shl()) {
1301 : shl = m.right().node();
1302 : shr = m.left().node();
1303 : } else {
1304 : return NoChange();
1305 : }
1306 :
1307 869 : Int32BinopMatcher mshl(shl);
1308 869 : Int32BinopMatcher mshr(shr);
1309 869 : if (mshl.left().node() != mshr.left().node()) return NoChange();
1310 :
1311 575 : if (mshl.right().HasValue() && mshr.right().HasValue()) {
1312 : // Case where y is a constant.
1313 382 : if (mshl.right().Value() + mshr.right().Value() != 32) return NoChange();
1314 : } else {
1315 : Node* sub = nullptr;
1316 : Node* y = nullptr;
1317 193 : if (mshl.right().IsInt32Sub()) {
1318 : sub = mshl.right().node();
1319 : y = mshr.right().node();
1320 157 : } else if (mshr.right().IsInt32Sub()) {
1321 : sub = mshr.right().node();
1322 : y = mshl.right().node();
1323 : } else {
1324 128 : return NoChange();
1325 : }
1326 :
1327 107 : Int32BinopMatcher msub(sub);
1328 214 : if (!msub.left().Is(32) || msub.right().node() != y) return NoChange();
1329 : }
1330 :
1331 447 : node->ReplaceInput(0, mshl.left().node());
1332 447 : node->ReplaceInput(1, mshr.right().node());
1333 447 : NodeProperties::ChangeOp(node, machine()->Word32Ror());
1334 : return Changed(node);
1335 : }
1336 :
1337 78040 : Reduction MachineOperatorReducer::ReduceWord32Or(Node* node) {
1338 : DCHECK_EQ(IrOpcode::kWord32Or, node->opcode());
1339 78040 : Int32BinopMatcher m(node);
1340 78040 : if (m.right().Is(0)) return Replace(m.left().node()); // x | 0 => x
1341 64387 : if (m.right().Is(-1)) return Replace(m.right().node()); // x | -1 => -1
1342 60970 : if (m.IsFoldable()) { // K | K => K
1343 17297 : return ReplaceInt32(m.left().Value() | m.right().Value());
1344 : }
1345 43673 : if (m.LeftEqualsRight()) return Replace(m.left().node()); // x | x => x
1346 :
1347 43624 : return TryMatchWord32Ror(node);
1348 : }
1349 :
1350 23909 : Reduction MachineOperatorReducer::ReduceWord32Xor(Node* node) {
1351 : DCHECK_EQ(IrOpcode::kWord32Xor, node->opcode());
1352 23909 : Int32BinopMatcher m(node);
1353 23909 : if (m.right().Is(0)) return Replace(m.left().node()); // x ^ 0 => x
1354 23357 : if (m.IsFoldable()) { // K ^ K => K
1355 17654 : return ReplaceInt32(m.left().Value() ^ m.right().Value());
1356 : }
1357 5703 : if (m.LeftEqualsRight()) return ReplaceInt32(0); // x ^ x => 0
1358 5908 : if (m.left().IsWord32Xor() && m.right().Is(-1)) {
1359 20 : Int32BinopMatcher mleft(m.left().node());
1360 20 : if (mleft.right().Is(-1)) { // (x ^ -1) ^ -1 => x
1361 20 : return Replace(mleft.left().node());
1362 : }
1363 : }
1364 :
1365 5669 : return TryMatchWord32Ror(node);
1366 : }
1367 :
1368 4856 : Reduction MachineOperatorReducer::ReduceFloat64InsertLowWord32(Node* node) {
1369 : DCHECK_EQ(IrOpcode::kFloat64InsertLowWord32, node->opcode());
1370 : Float64Matcher mlhs(node->InputAt(0));
1371 : Uint32Matcher mrhs(node->InputAt(1));
1372 4856 : if (mlhs.HasValue() && mrhs.HasValue()) {
1373 : return ReplaceFloat64(bit_cast<double>(
1374 4800 : (bit_cast<uint64_t>(mlhs.Value()) & uint64_t{0xFFFFFFFF00000000}) |
1375 : mrhs.Value()));
1376 : }
1377 : return NoChange();
1378 : }
1379 :
1380 :
1381 4856 : Reduction MachineOperatorReducer::ReduceFloat64InsertHighWord32(Node* node) {
1382 : DCHECK_EQ(IrOpcode::kFloat64InsertHighWord32, node->opcode());
1383 : Float64Matcher mlhs(node->InputAt(0));
1384 : Uint32Matcher mrhs(node->InputAt(1));
1385 4856 : if (mlhs.HasValue() && mrhs.HasValue()) {
1386 : return ReplaceFloat64(bit_cast<double>(
1387 9600 : (bit_cast<uint64_t>(mlhs.Value()) & uint64_t{0xFFFFFFFF}) |
1388 4800 : (static_cast<uint64_t>(mrhs.Value()) << 32)));
1389 : }
1390 : return NoChange();
1391 : }
1392 :
1393 :
1394 : namespace {
1395 :
1396 : bool IsFloat64RepresentableAsFloat32(const Float64Matcher& m) {
1397 194939 : if (m.HasValue()) {
1398 57624 : double v = m.Value();
1399 57624 : return DoubleToFloat32(v) == v;
1400 : }
1401 : return false;
1402 : }
1403 :
1404 : } // namespace
1405 :
1406 :
1407 261484 : Reduction MachineOperatorReducer::ReduceFloat64Compare(Node* node) {
1408 : DCHECK(IrOpcode::kFloat64Equal == node->opcode() ||
1409 : IrOpcode::kFloat64LessThan == node->opcode() ||
1410 : IrOpcode::kFloat64LessThanOrEqual == node->opcode());
1411 227702 : Float64BinopMatcher m(node);
1412 227702 : if (m.IsFoldable()) {
1413 32641 : switch (node->opcode()) {
1414 : case IrOpcode::kFloat64Equal:
1415 11820 : return ReplaceBool(m.left().Value() == m.right().Value());
1416 : case IrOpcode::kFloat64LessThan:
1417 10694 : return ReplaceBool(m.left().Value() < m.right().Value());
1418 : case IrOpcode::kFloat64LessThanOrEqual:
1419 10127 : return ReplaceBool(m.left().Value() <= m.right().Value());
1420 : default:
1421 0 : UNREACHABLE();
1422 : }
1423 196367 : } else if ((m.left().IsChangeFloat32ToFloat64() &&
1424 194534 : m.right().IsChangeFloat32ToFloat64()) ||
1425 779 : (m.left().IsChangeFloat32ToFloat64() &&
1426 389221 : IsFloat64RepresentableAsFloat32(m.right())) ||
1427 57159 : (IsFloat64RepresentableAsFloat32(m.left()) &&
1428 : m.right().IsChangeFloat32ToFloat64())) {
1429 : // As all Float32 values have an exact representation in Float64, comparing
1430 : // two Float64 values both converted from Float32 is equivalent to comparing
1431 : // the original Float32s, so we can ignore the conversions. We can also
1432 : // reduce comparisons of converted Float64 values against constants that
1433 : // can be represented exactly as Float32.
1434 1141 : switch (node->opcode()) {
1435 : case IrOpcode::kFloat64Equal:
1436 289 : NodeProperties::ChangeOp(node, machine()->Float32Equal());
1437 289 : break;
1438 : case IrOpcode::kFloat64LessThan:
1439 576 : NodeProperties::ChangeOp(node, machine()->Float32LessThan());
1440 576 : break;
1441 : case IrOpcode::kFloat64LessThanOrEqual:
1442 276 : NodeProperties::ChangeOp(node, machine()->Float32LessThanOrEqual());
1443 276 : break;
1444 : default:
1445 0 : UNREACHABLE();
1446 : }
1447 : node->ReplaceInput(
1448 1141 : 0, m.left().HasValue()
1449 240 : ? Float32Constant(static_cast<float>(m.left().Value()))
1450 2522 : : m.left().InputAt(0));
1451 : node->ReplaceInput(
1452 1141 : 1, m.right().HasValue()
1453 374 : ? Float32Constant(static_cast<float>(m.right().Value()))
1454 2656 : : m.right().InputAt(0));
1455 : return Changed(node);
1456 : }
1457 : return NoChange();
1458 : }
1459 :
1460 52000 : Reduction MachineOperatorReducer::ReduceFloat64RoundDown(Node* node) {
1461 : DCHECK_EQ(IrOpcode::kFloat64RoundDown, node->opcode());
1462 : Float64Matcher m(node->InputAt(0));
1463 52000 : if (m.HasValue()) {
1464 : return ReplaceFloat64(Floor(m.Value()));
1465 : }
1466 : return NoChange();
1467 : }
1468 :
1469 615328 : CommonOperatorBuilder* MachineOperatorReducer::common() const {
1470 615328 : return mcgraph()->common();
1471 : }
1472 :
1473 :
1474 625982 : MachineOperatorBuilder* MachineOperatorReducer::machine() const {
1475 625982 : return mcgraph()->machine();
1476 : }
1477 :
1478 730105 : Graph* MachineOperatorReducer::graph() const { return mcgraph()->graph(); }
1479 :
1480 : } // namespace compiler
1481 : } // namespace internal
1482 178779 : } // namespace v8
|