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 1671249 : MachineOperatorReducer::MachineOperatorReducer(Editor* editor,
23 : MachineGraph* mcgraph,
24 : bool allow_signalling_nan)
25 : : AdvancedReducer(editor),
26 : mcgraph_(mcgraph),
27 1671249 : allow_signalling_nan_(allow_signalling_nan) {}
28 :
29 : MachineOperatorReducer::~MachineOperatorReducer() = default;
30 :
31 :
32 66983 : Node* MachineOperatorReducer::Float32Constant(volatile float value) {
33 200949 : return graph()->NewNode(common()->Float32Constant(value));
34 : }
35 :
36 :
37 95926 : Node* MachineOperatorReducer::Float64Constant(volatile double value) {
38 191852 : return mcgraph()->Float64Constant(value);
39 : }
40 :
41 :
42 547731 : Node* MachineOperatorReducer::Int32Constant(int32_t value) {
43 547731 : return mcgraph()->Int32Constant(value);
44 : }
45 :
46 :
47 546885 : Node* MachineOperatorReducer::Int64Constant(int64_t value) {
48 1093773 : 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 101944 : Node* MachineOperatorReducer::Word32And(Node* lhs, Node* rhs) {
67 101944 : Node* const node = graph()->NewNode(machine()->Word32And(), lhs, rhs);
68 101944 : Reduction const reduction = ReduceWord32And(node);
69 101944 : return reduction.Changed() ? reduction.replacement() : node;
70 : }
71 :
72 :
73 7040 : Node* MachineOperatorReducer::Word32Sar(Node* lhs, uint32_t rhs) {
74 7040 : if (rhs == 0) return lhs;
75 9906 : return graph()->NewNode(machine()->Word32Sar(), lhs, Uint32Constant(rhs));
76 : }
77 :
78 :
79 8955 : Node* MachineOperatorReducer::Word32Shr(Node* lhs, uint32_t rhs) {
80 8955 : if (rhs == 0) return lhs;
81 16000 : 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 7628 : Node* MachineOperatorReducer::Int32Add(Node* lhs, Node* rhs) {
91 7628 : Node* const node = graph()->NewNode(machine()->Int32Add(), lhs, rhs);
92 7628 : Reduction const reduction = ReduceInt32Add(node);
93 7628 : return reduction.Changed() ? reduction.replacement() : node;
94 : }
95 :
96 :
97 1733 : Node* MachineOperatorReducer::Int32Sub(Node* lhs, Node* rhs) {
98 1733 : Node* const node = graph()->NewNode(machine()->Int32Sub(), lhs, rhs);
99 1733 : Reduction const reduction = ReduceInt32Sub(node);
100 1733 : return reduction.Changed() ? reduction.replacement() : node;
101 : }
102 :
103 :
104 4043 : Node* MachineOperatorReducer::Int32Mul(Node* lhs, Node* rhs) {
105 8086 : return graph()->NewNode(machine()->Int32Mul(), lhs, rhs);
106 : }
107 :
108 :
109 5718 : 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 5718 : base::SignedDivisionByConstant(bit_cast<uint32_t>(divisor));
114 : Node* quotient = graph()->NewNode(machine()->Int32MulHigh(), dividend,
115 5718 : Uint32Constant(mag.multiplier));
116 11436 : if (divisor > 0 && bit_cast<int32_t>(mag.multiplier) < 0) {
117 1157 : quotient = Int32Add(quotient, dividend);
118 4561 : } else if (divisor < 0 && bit_cast<int32_t>(mag.multiplier) > 0) {
119 0 : quotient = Int32Sub(quotient, dividend);
120 : }
121 5718 : return Int32Add(Word32Sar(quotient, mag.shift), Word32Shr(dividend, 31));
122 : }
123 :
124 :
125 1242 : 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 1242 : dividend = Word32Shr(dividend, shift);
131 1242 : divisor >>= shift;
132 : // Compute the magic number for the (shifted) divisor.
133 : base::MagicNumbersForDivision<uint32_t> const mag =
134 1242 : base::UnsignedDivisionByConstant(divisor, shift);
135 : Node* quotient = graph()->NewNode(machine()->Uint32MulHigh(), dividend,
136 2484 : Uint32Constant(mag.multiplier));
137 1242 : if (mag.add) {
138 : DCHECK_LE(1u, mag.shift);
139 : quotient = Word32Shr(
140 : Int32Add(Word32Shr(Int32Sub(dividend, quotient), 1), quotient),
141 29 : mag.shift - 1);
142 : } else {
143 1213 : quotient = Word32Shr(quotient, mag.shift);
144 : }
145 1242 : return quotient;
146 : }
147 :
148 :
149 : // Perform constant folding and strength reduction on machine operators.
150 114118468 : Reduction MachineOperatorReducer::Reduce(Node* node) {
151 114118468 : switch (node->opcode()) {
152 : case IrOpcode::kProjection:
153 249993 : return ReduceProjection(ProjectionIndexOf(node->op()), node->InputAt(0));
154 : case IrOpcode::kWord32And:
155 527895 : return ReduceWord32And(node);
156 : case IrOpcode::kWord32Or:
157 76233 : return ReduceWord32Or(node);
158 : case IrOpcode::kWord32Xor:
159 24089 : return ReduceWord32Xor(node);
160 : case IrOpcode::kWord32Shl:
161 45747 : return ReduceWord32Shl(node);
162 : case IrOpcode::kWord64Shl:
163 618249 : return ReduceWord64Shl(node);
164 : case IrOpcode::kWord32Shr:
165 85655 : return ReduceWord32Shr(node);
166 : case IrOpcode::kWord64Shr:
167 47427 : return ReduceWord64Shr(node);
168 : case IrOpcode::kWord32Sar:
169 31414 : return ReduceWord32Sar(node);
170 : case IrOpcode::kWord64Sar:
171 343644 : 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 970730 : Int32BinopMatcher m(node);
183 970730 : if (m.IsFoldable()) { // K == K => K
184 66933 : return ReplaceBool(m.left().Value() == m.right().Value());
185 : }
186 938443 : if (m.left().IsInt32Sub() && m.right().Is(0)) { // x - y == 0 => x == y
187 744 : Int32BinopMatcher msub(m.left().node());
188 744 : node->ReplaceInput(0, msub.left().node());
189 744 : node->ReplaceInput(1, msub.right().node());
190 : return Changed(node);
191 : }
192 : // TODO(turbofan): fold HeapConstant, ExternalReference, pointer compares
193 936899 : if (m.LeftEqualsRight()) return ReplaceBool(true); // x == x => true
194 936884 : break;
195 : }
196 : case IrOpcode::kWord64Equal: {
197 1922436 : Int64BinopMatcher m(node);
198 1922437 : if (m.IsFoldable()) { // K == K => K
199 11226 : return ReplaceBool(m.left().Value() == m.right().Value());
200 : }
201 1929264 : 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 1921099 : if (m.LeftEqualsRight()) return ReplaceBool(true); // x == x => true
209 1911821 : break;
210 : }
211 : case IrOpcode::kInt32Add:
212 413212 : return ReduceInt32Add(node);
213 : case IrOpcode::kInt64Add:
214 1637687 : return ReduceInt64Add(node);
215 : case IrOpcode::kInt32Sub:
216 56169 : return ReduceInt32Sub(node);
217 : case IrOpcode::kInt64Sub:
218 314948 : return ReduceInt64Sub(node);
219 : case IrOpcode::kInt32Mul: {
220 43011 : Int32BinopMatcher m(node);
221 62011 : if (m.right().Is(0)) return Replace(m.right().node()); // x * 0 => 0
222 42642 : if (m.right().Is(1)) return Replace(m.left().node()); // x * 1 => x
223 42341 : if (m.IsFoldable()) { // K * K => K
224 : return ReplaceInt32(
225 16555 : base::MulWithWraparound(m.left().Value(), m.right().Value()));
226 : }
227 25786 : if (m.right().Is(-1)) { // x * -1 => 0 - x
228 76 : node->ReplaceInput(0, Int32Constant(0));
229 76 : node->ReplaceInput(1, m.left().node());
230 76 : NodeProperties::ChangeOp(node, machine()->Int32Sub());
231 : return Changed(node);
232 : }
233 25710 : if (m.right().IsPowerOf2()) { // x * 2^n => x << n
234 3398 : node->ReplaceInput(1, Int32Constant(WhichPowerOf2(m.right().Value())));
235 1699 : NodeProperties::ChangeOp(node, machine()->Word32Shl());
236 1699 : Reduction reduction = ReduceWord32Shl(node);
237 1699 : return reduction.Changed() ? reduction : Changed(node);
238 : }
239 24011 : break;
240 : }
241 : case IrOpcode::kInt32MulWithOverflow: {
242 7210 : Int32BinopMatcher m(node);
243 7210 : if (m.right().Is(2)) {
244 189 : node->ReplaceInput(1, m.left().node());
245 189 : NodeProperties::ChangeOp(node, machine()->Int32AddWithOverflow());
246 3336 : return Changed(node);
247 : }
248 7021 : if (m.right().Is(-1)) {
249 3147 : node->ReplaceInput(0, Int32Constant(0));
250 3147 : node->ReplaceInput(1, m.left().node());
251 3147 : NodeProperties::ChangeOp(node, machine()->Int32SubWithOverflow());
252 : return Changed(node);
253 : }
254 3874 : break;
255 : }
256 : case IrOpcode::kInt32Div:
257 21215 : return ReduceInt32Div(node);
258 : case IrOpcode::kUint32Div:
259 19345 : return ReduceUint32Div(node);
260 : case IrOpcode::kInt32Mod:
261 31656 : return ReduceInt32Mod(node);
262 : case IrOpcode::kUint32Mod:
263 21094 : return ReduceUint32Mod(node);
264 : case IrOpcode::kInt32LessThan: {
265 266772 : Int32BinopMatcher m(node);
266 266780 : if (m.IsFoldable()) { // K < K => K
267 40724 : return ReplaceBool(m.left().Value() < m.right().Value());
268 : }
269 246460 : if (m.LeftEqualsRight()) return ReplaceBool(false); // x < x => false
270 248222 : if (m.left().IsWord32Or() && m.right().Is(0)) {
271 : // (x | K) < 0 => true or (K | x) < 0 => true iff K < 0
272 1731 : Int32BinopMatcher mleftmatcher(m.left().node());
273 3462 : if (mleftmatcher.left().IsNegative() ||
274 : mleftmatcher.right().IsNegative()) {
275 72 : return ReplaceBool(true);
276 : }
277 : }
278 246376 : break;
279 : }
280 : case IrOpcode::kInt32LessThanOrEqual: {
281 47216 : Int32BinopMatcher m(node);
282 47216 : if (m.IsFoldable()) { // K <= K => K
283 35327 : return ReplaceBool(m.left().Value() <= m.right().Value());
284 : }
285 29555 : if (m.LeftEqualsRight()) return ReplaceBool(true); // x <= x => true
286 29550 : break;
287 : }
288 : case IrOpcode::kUint32LessThan: {
289 194986 : Uint32BinopMatcher m(node);
290 212699 : if (m.left().Is(kMaxUInt32)) return ReplaceBool(false); // M < x => false
291 194671 : if (m.right().Is(0)) return ReplaceBool(false); // x < 0 => false
292 194233 : if (m.IsFoldable()) { // K < K => K
293 16535 : return ReplaceBool(m.left().Value() < m.right().Value());
294 : }
295 177698 : if (m.LeftEqualsRight()) return ReplaceBool(false); // x < x => false
296 177554 : if (m.left().IsWord32Sar() && m.right().HasValue()) {
297 306 : Int32BinopMatcher mleft(m.left().node());
298 306 : if (mleft.right().HasValue()) {
299 : // (x >> K) < C => x < (C << K)
300 : // when C < (M >> K)
301 306 : const uint32_t c = m.right().Value();
302 306 : const uint32_t k = mleft.right().Value() & 0x1F;
303 306 : if (c < static_cast<uint32_t>(kMaxInt >> k)) {
304 283 : node->ReplaceInput(0, mleft.left().node());
305 566 : node->ReplaceInput(1, Uint32Constant(c << k));
306 283 : return Changed(node);
307 : }
308 : // TODO(turbofan): else the comparison is always true.
309 : }
310 : }
311 177271 : break;
312 : }
313 : case IrOpcode::kUint32LessThanOrEqual: {
314 63020 : Uint32BinopMatcher m(node);
315 80357 : if (m.left().Is(0)) return ReplaceBool(true); // 0 <= x => true
316 62449 : if (m.right().Is(kMaxUInt32)) return ReplaceBool(true); // x <= M => true
317 62159 : if (m.IsFoldable()) { // K <= K => K
318 16472 : return ReplaceBool(m.left().Value() <= m.right().Value());
319 : }
320 45687 : if (m.LeftEqualsRight()) return ReplaceBool(true); // x <= x => true
321 45681 : break;
322 : }
323 : case IrOpcode::kFloat32Sub: {
324 66142 : Float32BinopMatcher m(node);
325 133434 : 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 65567 : 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 64412 : 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 63287 : if (m.IsFoldable()) { // L - R => (L - R)
338 63280 : return ReplaceFloat32(m.left().Value() - m.right().Value());
339 : }
340 7 : 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 6 : break;
358 : }
359 : case IrOpcode::kFloat64Add: {
360 146107 : Float64BinopMatcher m(node);
361 146110 : if (m.IsFoldable()) { // K + K => K
362 24133 : return ReplaceFloat64(m.left().Value() + m.right().Value());
363 : }
364 134044 : break;
365 : }
366 : case IrOpcode::kFloat64Sub: {
367 36613 : Float64BinopMatcher m(node);
368 73874 : if (allow_signalling_nan_ && m.right().Is(0) &&
369 648 : (Double(m.right().Value()).Sign() > 0)) {
370 21576 : return Replace(m.left().node()); // x - 0 => x
371 : }
372 36218 : 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 35680 : 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 35171 : if (m.IsFoldable()) { // L - R => (L - R)
381 11635 : return ReplaceFloat64(m.left().Value() - m.right().Value());
382 : }
383 23536 : if (allow_signalling_nan_ && m.left().IsMinusZero()) {
384 : // -0.0 - round_down(-0.0 - R) => round_up(R)
385 16996 : 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 8499 : node->RemoveInput(0);
397 8499 : NodeProperties::ChangeOp(node, machine()->Float64Neg());
398 : return Changed(node);
399 : }
400 15037 : break;
401 : }
402 : case IrOpcode::kFloat64Mul: {
403 25825 : Float64BinopMatcher m(node);
404 51650 : if (allow_signalling_nan_ && m.right().Is(1))
405 10735 : return Replace(m.left().node()); // x * 1.0 => x
406 25771 : if (m.right().Is(-1)) { // x * -1.0 => -0.0 - x
407 8730 : node->ReplaceInput(0, Float64Constant(-0.0));
408 8730 : node->ReplaceInput(1, m.left().node());
409 8730 : NodeProperties::ChangeOp(node, machine()->Float64Sub());
410 : return Changed(node);
411 : }
412 17041 : 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 17008 : if (m.IsFoldable()) { // K * K => K
417 1765 : return ReplaceFloat64(m.left().Value() * m.right().Value());
418 : }
419 15243 : if (m.right().Is(2)) { // x * 2.0 => x + x
420 153 : node->ReplaceInput(1, m.left().node());
421 153 : NodeProperties::ChangeOp(node, machine()->Float64Add());
422 : return Changed(node);
423 : }
424 15090 : break;
425 : }
426 : case IrOpcode::kFloat64Div: {
427 30231 : Float64BinopMatcher m(node);
428 60462 : if (allow_signalling_nan_ && m.right().Is(1))
429 6003 : 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 30115 : 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 30085 : 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 30039 : if (m.IsFoldable()) { // K / K => K
440 : return ReplaceFloat64(
441 2963 : base::Divide(m.left().Value(), m.right().Value()));
442 : }
443 54152 : if (allow_signalling_nan_ && m.right().Is(-1)) { // x / -1.0 => -x
444 39 : node->RemoveInput(1);
445 39 : NodeProperties::ChangeOp(node, machine()->Float64Neg());
446 : return Changed(node);
447 : }
448 27037 : 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 5618 : node->ReplaceInput(1, Float64Constant(1.0 / m.right().Value()));
453 2809 : NodeProperties::ChangeOp(node, machine()->Float64Mul());
454 : return Changed(node);
455 : }
456 24228 : break;
457 : }
458 : case IrOpcode::kFloat64Mod: {
459 3164 : Float64BinopMatcher m(node);
460 3164 : if (m.right().Is(0)) { // x % 0 => NaN
461 1243 : return ReplaceFloat64(std::numeric_limits<double>::quiet_NaN());
462 : }
463 3013 : if (m.right().IsNaN()) { // x % NaN => NaN
464 : return Replace(m.right().node());
465 : }
466 2976 : if (m.left().IsNaN()) { // NaN % x => NaN
467 : return Replace(m.left().node());
468 : }
469 2949 : if (m.IsFoldable()) { // K % K => K
470 1028 : return ReplaceFloat64(Modulo(m.left().Value(), m.right().Value()));
471 : }
472 1921 : 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 156 : 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 172 : 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 10075 : Float64BinopMatcher m(node);
506 10075 : if (m.right().IsNaN()) {
507 10007 : return Replace(m.right().node());
508 : }
509 10074 : if (m.left().IsNaN()) {
510 : return Replace(m.left().node());
511 : }
512 10073 : if (m.IsFoldable()) {
513 : return ReplaceFloat64(
514 10005 : base::ieee754::atan2(m.left().Value(), m.right().Value()));
515 : }
516 68 : 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 339 : 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 233 : 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 490 : 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 11222 : Float64BinopMatcher m(node);
565 11222 : if (m.IsFoldable()) {
566 21666 : return ReplaceFloat64(Pow(m.left().Value(), m.right().Value()));
567 390 : } else if (m.right().Is(0.0)) { // x ** +-0.0 => 1.0
568 : return ReplaceFloat64(1.0);
569 388 : } else if (m.right().Is(-2.0)) { // x ** -2.0 => 1 / (x * x)
570 0 : node->ReplaceInput(0, Float64Constant(1.0));
571 0 : node->ReplaceInput(1, Float64Mul(m.left().node(), m.left().node()));
572 0 : NodeProperties::ChangeOp(node, machine()->Float64Div());
573 : return Changed(node);
574 388 : } else if (m.right().Is(2.0)) { // x ** 2.0 => x * x
575 0 : node->ReplaceInput(1, m.left().node());
576 0 : NodeProperties::ChangeOp(node, machine()->Float64Mul());
577 : return Changed(node);
578 388 : } else if (m.right().Is(-0.5)) {
579 : // x ** 0.5 => 1 / (if x <= -Infinity then Infinity else sqrt(0.0 + x))
580 0 : node->ReplaceInput(0, Float64Constant(1.0));
581 0 : node->ReplaceInput(1, Float64PowHalf(m.left().node()));
582 0 : NodeProperties::ChangeOp(node, machine()->Float64Div());
583 : return Changed(node);
584 388 : } else if (m.right().Is(0.5)) {
585 : // x ** 0.5 => if x <= -Infinity then Infinity else sqrt(0.0 + x)
586 0 : return Replace(Float64PowHalf(m.left().node()));
587 : }
588 388 : break;
589 : }
590 : case IrOpcode::kFloat64Sin: {
591 : Float64Matcher m(node->InputAt(0));
592 367 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::sin(m.Value()));
593 : break;
594 : }
595 : case IrOpcode::kFloat64Sinh: {
596 : Float64Matcher m(node->InputAt(0));
597 170 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::sinh(m.Value()));
598 : break;
599 : }
600 : case IrOpcode::kFloat64Tan: {
601 : Float64Matcher m(node->InputAt(0));
602 223 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::tan(m.Value()));
603 : break;
604 : }
605 : case IrOpcode::kFloat64Tanh: {
606 : Float64Matcher m(node->InputAt(0));
607 170 : if (m.HasValue()) return ReplaceFloat64(base::ieee754::tanh(m.Value()));
608 : break;
609 : }
610 : case IrOpcode::kChangeFloat32ToFloat64: {
611 : Float32Matcher m(node->InputAt(0));
612 14146 : if (m.HasValue()) {
613 151 : if (!allow_signalling_nan_ && std::isnan(m.Value())) {
614 : // Do some calculation to make guarantee the value is a quiet NaN.
615 0 : return ReplaceFloat64(m.Value() + m.Value());
616 : }
617 151 : return ReplaceFloat64(m.Value());
618 : }
619 : break;
620 : }
621 : case IrOpcode::kChangeFloat64ToInt32: {
622 : Float64Matcher m(node->InputAt(0));
623 3657 : if (m.HasValue()) return ReplaceInt32(FastD2IChecked(m.Value()));
624 3515 : if (m.IsChangeInt32ToFloat64()) return Replace(m.node()->InputAt(0));
625 : break;
626 : }
627 : case IrOpcode::kChangeFloat64ToInt64: {
628 : Float64Matcher m(node->InputAt(0));
629 140 : if (m.HasValue()) return ReplaceInt64(static_cast<int64_t>(m.Value()));
630 35 : if (m.IsChangeInt64ToFloat64()) return Replace(m.node()->InputAt(0));
631 : break;
632 : }
633 : case IrOpcode::kChangeFloat64ToUint32: {
634 : Float64Matcher m(node->InputAt(0));
635 841 : if (m.HasValue()) return ReplaceInt32(FastD2UI(m.Value()));
636 727 : if (m.IsChangeUint32ToFloat64()) return Replace(m.node()->InputAt(0));
637 : break;
638 : }
639 : case IrOpcode::kChangeInt32ToFloat64: {
640 : Int32Matcher m(node->InputAt(0));
641 254985 : if (m.HasValue()) return ReplaceFloat64(FastI2D(m.Value()));
642 : break;
643 : }
644 : case IrOpcode::kChangeInt32ToInt64: {
645 : Int32Matcher m(node->InputAt(0));
646 216532 : if (m.HasValue()) return ReplaceInt64(m.Value());
647 : break;
648 : }
649 : case IrOpcode::kChangeInt64ToFloat64: {
650 : Int64Matcher m(node->InputAt(0));
651 1058 : if (m.HasValue()) return ReplaceFloat64(static_cast<double>(m.Value()));
652 561 : if (m.IsChangeFloat64ToInt64()) return Replace(m.node()->InputAt(0));
653 : break;
654 : }
655 : case IrOpcode::kChangeUint32ToFloat64: {
656 : Uint32Matcher m(node->InputAt(0));
657 6494 : if (m.HasValue()) return ReplaceFloat64(FastUI2D(m.Value()));
658 : break;
659 : }
660 : case IrOpcode::kChangeUint32ToUint64: {
661 : Uint32Matcher m(node->InputAt(0));
662 300957 : if (m.HasValue()) return ReplaceInt64(static_cast<uint64_t>(m.Value()));
663 : break;
664 : }
665 : case IrOpcode::kTruncateFloat64ToWord32: {
666 : Float64Matcher m(node->InputAt(0));
667 24428 : if (m.HasValue()) return ReplaceInt32(DoubleToInt32(m.Value()));
668 21137 : if (m.IsChangeInt32ToFloat64()) return Replace(m.node()->InputAt(0));
669 : return NoChange();
670 : }
671 : case IrOpcode::kTruncateInt64ToInt32: {
672 : Int64Matcher m(node->InputAt(0));
673 308847 : if (m.HasValue()) return ReplaceInt32(static_cast<int32_t>(m.Value()));
674 298075 : if (m.IsChangeInt32ToInt64()) return Replace(m.node()->InputAt(0));
675 : break;
676 : }
677 : case IrOpcode::kTruncateFloat64ToFloat32: {
678 : Float64Matcher m(node->InputAt(0));
679 9334 : if (m.HasValue()) {
680 791 : if (!allow_signalling_nan_ && std::isnan(m.Value())) {
681 : // Do some calculation to make guarantee the value is a quiet NaN.
682 0 : return ReplaceFloat32(DoubleToFloat32(m.Value() + m.Value()));
683 : }
684 : return ReplaceFloat32(DoubleToFloat32(m.Value()));
685 : }
686 8543 : if (allow_signalling_nan_ && m.IsChangeFloat32ToFloat64())
687 : return Replace(m.node()->InputAt(0));
688 : break;
689 : }
690 : case IrOpcode::kRoundFloat64ToInt32: {
691 : Float64Matcher m(node->InputAt(0));
692 70779 : if (m.HasValue()) {
693 274 : return ReplaceInt32(DoubleToInt32(m.Value()));
694 : }
695 70505 : if (m.IsChangeInt32ToFloat64()) return Replace(m.node()->InputAt(0));
696 : break;
697 : }
698 : case IrOpcode::kFloat64InsertLowWord32:
699 4856 : return ReduceFloat64InsertLowWord32(node);
700 : case IrOpcode::kFloat64InsertHighWord32:
701 4856 : return ReduceFloat64InsertHighWord32(node);
702 : case IrOpcode::kStore:
703 : case IrOpcode::kUnalignedStore:
704 2605090 : return ReduceStore(node);
705 : case IrOpcode::kFloat64Equal:
706 : case IrOpcode::kFloat64LessThan:
707 : case IrOpcode::kFloat64LessThanOrEqual:
708 230071 : return ReduceFloat64Compare(node);
709 : case IrOpcode::kFloat64RoundDown:
710 53217 : return ReduceFloat64RoundDown(node);
711 : case IrOpcode::kBitcastTaggedToWord: {
712 : NodeMatcher m(node->InputAt(0));
713 1090495 : if (m.IsBitcastWordToTaggedSigned()) {
714 : RelaxEffectsAndControls(node);
715 : return Replace(m.InputAt(0));
716 : }
717 : break;
718 : }
719 : default:
720 : break;
721 : }
722 : return NoChange();
723 : }
724 :
725 535068 : Reduction MachineOperatorReducer::ReduceInt32Add(Node* node) {
726 : DCHECK_EQ(IrOpcode::kInt32Add, node->opcode());
727 535068 : Int32BinopMatcher m(node);
728 535075 : if (m.right().Is(0)) return Replace(m.left().node()); // x + 0 => x
729 510495 : if (m.IsFoldable()) { // K + K => K
730 : return ReplaceInt32(
731 38927 : base::AddWithWraparound(m.left().Value(), m.right().Value()));
732 : }
733 471568 : if (m.left().IsInt32Sub()) {
734 1635 : Int32BinopMatcher mleft(m.left().node());
735 1635 : if (mleft.left().Is(0)) { // (0 - x) + y => y - x
736 122 : node->ReplaceInput(0, m.right().node());
737 122 : node->ReplaceInput(1, mleft.right().node());
738 122 : NodeProperties::ChangeOp(node, machine()->Int32Sub());
739 122 : Reduction const reduction = ReduceInt32Sub(node);
740 122 : return reduction.Changed() ? reduction : Changed(node);
741 : }
742 : }
743 471446 : if (m.right().IsInt32Sub()) {
744 536 : Int32BinopMatcher mright(m.right().node());
745 536 : if (mright.left().Is(0)) { // y + (0 - x) => y - x
746 48 : node->ReplaceInput(1, mright.right().node());
747 48 : NodeProperties::ChangeOp(node, machine()->Int32Sub());
748 48 : Reduction const reduction = ReduceInt32Sub(node);
749 48 : return reduction.Changed() ? reduction : Changed(node);
750 : }
751 : }
752 : return NoChange();
753 : }
754 :
755 1898275 : Reduction MachineOperatorReducer::ReduceInt64Add(Node* node) {
756 : DCHECK_EQ(IrOpcode::kInt64Add, node->opcode());
757 1898275 : Int64BinopMatcher m(node);
758 1898275 : if (m.right().Is(0)) return Replace(m.left().node()); // x + 0 => 0
759 1887987 : if (m.IsFoldable()) {
760 : return ReplaceInt64(
761 78447 : base::AddWithWraparound(m.left().Value(), m.right().Value()));
762 : }
763 : return NoChange();
764 : }
765 :
766 58127 : Reduction MachineOperatorReducer::ReduceInt32Sub(Node* node) {
767 : DCHECK_EQ(IrOpcode::kInt32Sub, node->opcode());
768 58127 : Int32BinopMatcher m(node);
769 58127 : if (m.right().Is(0)) return Replace(m.left().node()); // x - 0 => x
770 57476 : if (m.IsFoldable()) { // K - K => K
771 : return ReplaceInt32(
772 19386 : base::SubWithWraparound(m.left().Value(), m.right().Value()));
773 : }
774 38090 : if (m.LeftEqualsRight()) return ReplaceInt32(0); // x - x => 0
775 38090 : if (m.right().HasValue()) { // x - K => x + -K
776 : node->ReplaceInput(
777 27972 : 1, Int32Constant(base::NegateWithWraparound(m.right().Value())));
778 13986 : NodeProperties::ChangeOp(node, machine()->Int32Add());
779 13986 : Reduction const reduction = ReduceInt32Add(node);
780 13986 : return reduction.Changed() ? reduction : Changed(node);
781 : }
782 : return NoChange();
783 : }
784 :
785 314947 : Reduction MachineOperatorReducer::ReduceInt64Sub(Node* node) {
786 : DCHECK_EQ(IrOpcode::kInt64Sub, node->opcode());
787 314947 : Int64BinopMatcher m(node);
788 314946 : if (m.right().Is(0)) return Replace(m.left().node()); // x - 0 => x
789 310834 : if (m.IsFoldable()) { // K - K => K
790 : return ReplaceInt64(
791 34169 : base::SubWithWraparound(m.left().Value(), m.right().Value()));
792 : }
793 276665 : if (m.LeftEqualsRight()) return Replace(Int64Constant(0)); // x - x => 0
794 276657 : if (m.right().HasValue()) { // x - K => x + -K
795 : node->ReplaceInput(
796 521172 : 1, Int64Constant(base::NegateWithWraparound(m.right().Value())));
797 260589 : NodeProperties::ChangeOp(node, machine()->Int64Add());
798 260588 : Reduction const reduction = ReduceInt64Add(node);
799 260588 : return reduction.Changed() ? reduction : Changed(node);
800 : }
801 : return NoChange();
802 : }
803 :
804 21215 : Reduction MachineOperatorReducer::ReduceInt32Div(Node* node) {
805 21215 : Int32BinopMatcher m(node);
806 21215 : if (m.left().Is(0)) return Replace(m.left().node()); // 0 / x => 0
807 20924 : if (m.right().Is(0)) return Replace(m.right().node()); // x / 0 => 0
808 20923 : if (m.right().Is(1)) return Replace(m.left().node()); // x / 1 => x
809 20594 : if (m.IsFoldable()) { // K / K => K
810 : return ReplaceInt32(
811 16014 : base::bits::SignedDiv32(m.left().Value(), m.right().Value()));
812 : }
813 4580 : if (m.LeftEqualsRight()) { // x / x => x != 0
814 : Node* const zero = Int32Constant(0);
815 5 : return Replace(Word32Equal(Word32Equal(m.left().node(), zero), zero));
816 : }
817 4575 : if (m.right().Is(-1)) { // x / -1 => 0 - x
818 32 : node->ReplaceInput(0, Int32Constant(0));
819 32 : node->ReplaceInput(1, m.left().node());
820 32 : node->TrimInputCount(2);
821 32 : NodeProperties::ChangeOp(node, machine()->Int32Sub());
822 : return Changed(node);
823 : }
824 4543 : if (m.right().HasValue()) {
825 3573 : int32_t const divisor = m.right().Value();
826 : Node* const dividend = m.left().node();
827 : Node* quotient = dividend;
828 3573 : if (base::bits::IsPowerOfTwo(Abs(divisor))) {
829 724 : uint32_t const shift = WhichPowerOf2(Abs(divisor));
830 : DCHECK_NE(0u, shift);
831 724 : if (shift > 1) {
832 598 : quotient = Word32Sar(quotient, 31);
833 : }
834 724 : quotient = Int32Add(Word32Shr(quotient, 32u - shift), dividend);
835 724 : quotient = Word32Sar(quotient, shift);
836 : } else {
837 2849 : quotient = Int32Div(quotient, Abs(divisor));
838 : }
839 3573 : if (divisor < 0) {
840 1154 : node->ReplaceInput(0, Int32Constant(0));
841 1154 : node->ReplaceInput(1, quotient);
842 1154 : node->TrimInputCount(2);
843 1154 : NodeProperties::ChangeOp(node, machine()->Int32Sub());
844 : return Changed(node);
845 : }
846 : return Replace(quotient);
847 : }
848 : return NoChange();
849 : }
850 :
851 :
852 19345 : Reduction MachineOperatorReducer::ReduceUint32Div(Node* node) {
853 19345 : Uint32BinopMatcher m(node);
854 19345 : if (m.left().Is(0)) return Replace(m.left().node()); // 0 / x => 0
855 19001 : if (m.right().Is(0)) return Replace(m.right().node()); // x / 0 => 0
856 18953 : if (m.right().Is(1)) return Replace(m.left().node()); // x / 1 => x
857 18609 : if (m.IsFoldable()) { // K / K => K
858 : return ReplaceUint32(
859 18154 : base::bits::UnsignedDiv32(m.left().Value(), m.right().Value()));
860 : }
861 455 : if (m.LeftEqualsRight()) { // x / x => x != 0
862 : Node* const zero = Int32Constant(0);
863 1 : return Replace(Word32Equal(Word32Equal(m.left().node(), zero), zero));
864 : }
865 454 : if (m.right().HasValue()) {
866 : Node* const dividend = m.left().node();
867 289 : uint32_t const divisor = m.right().Value();
868 289 : if (base::bits::IsPowerOfTwo(divisor)) { // x / 2^n => x >> n
869 442 : node->ReplaceInput(1, Uint32Constant(WhichPowerOf2(m.right().Value())));
870 221 : node->TrimInputCount(2);
871 221 : NodeProperties::ChangeOp(node, machine()->Word32Shr());
872 : return Changed(node);
873 : } else {
874 68 : return Replace(Uint32Div(dividend, divisor));
875 : }
876 : }
877 : return NoChange();
878 : }
879 :
880 :
881 31656 : Reduction MachineOperatorReducer::ReduceInt32Mod(Node* node) {
882 31656 : Int32BinopMatcher m(node);
883 31656 : if (m.left().Is(0)) return Replace(m.left().node()); // 0 % x => 0
884 31252 : if (m.right().Is(0)) return Replace(m.right().node()); // x % 0 => 0
885 31152 : if (m.right().Is(1)) return ReplaceInt32(0); // x % 1 => 0
886 30833 : if (m.right().Is(-1)) return ReplaceInt32(0); // x % -1 => 0
887 30547 : if (m.LeftEqualsRight()) return ReplaceInt32(0); // x % x => 0
888 30538 : if (m.IsFoldable()) { // K % K => K
889 : return ReplaceInt32(
890 25566 : base::bits::SignedMod32(m.left().Value(), m.right().Value()));
891 : }
892 4972 : if (m.right().HasValue()) {
893 : Node* const dividend = m.left().node();
894 3721 : uint32_t const divisor = Abs(m.right().Value());
895 3721 : if (base::bits::IsPowerOfTwo(divisor)) {
896 852 : uint32_t const mask = divisor - 1;
897 : Node* const zero = Int32Constant(0);
898 : Diamond d(graph(), common(),
899 : graph()->NewNode(machine()->Int32LessThan(), dividend, zero),
900 1704 : BranchHint::kFalse);
901 : return Replace(
902 : d.Phi(MachineRepresentation::kWord32,
903 : Int32Sub(zero, Word32And(Int32Sub(zero, dividend), mask)),
904 852 : Word32And(dividend, mask)));
905 : } else {
906 2869 : Node* quotient = Int32Div(dividend, divisor);
907 : DCHECK_EQ(dividend, node->InputAt(0));
908 2869 : node->ReplaceInput(1, Int32Mul(quotient, Int32Constant(divisor)));
909 2869 : node->TrimInputCount(2);
910 2869 : NodeProperties::ChangeOp(node, machine()->Int32Sub());
911 : }
912 : return Changed(node);
913 : }
914 : return NoChange();
915 : }
916 :
917 :
918 21094 : Reduction MachineOperatorReducer::ReduceUint32Mod(Node* node) {
919 21094 : Uint32BinopMatcher m(node);
920 21094 : if (m.left().Is(0)) return Replace(m.left().node()); // 0 % x => 0
921 20710 : if (m.right().Is(0)) return Replace(m.right().node()); // x % 0 => 0
922 20662 : if (m.right().Is(1)) return ReplaceUint32(0); // x % 1 => 0
923 20318 : if (m.LeftEqualsRight()) return ReplaceInt32(0); // x % x => 0
924 20316 : if (m.IsFoldable()) { // K % K => K
925 : return ReplaceUint32(
926 18201 : base::bits::UnsignedMod32(m.left().Value(), m.right().Value()));
927 : }
928 2115 : if (m.right().HasValue()) {
929 : Node* const dividend = m.left().node();
930 1664 : uint32_t const divisor = m.right().Value();
931 1664 : if (base::bits::IsPowerOfTwo(divisor)) { // x % 2^n => x & 2^n-1
932 980 : node->ReplaceInput(1, Uint32Constant(m.right().Value() - 1));
933 490 : node->TrimInputCount(2);
934 490 : NodeProperties::ChangeOp(node, machine()->Word32And());
935 : } else {
936 1174 : Node* quotient = Uint32Div(dividend, divisor);
937 : DCHECK_EQ(dividend, node->InputAt(0));
938 1174 : node->ReplaceInput(1, Int32Mul(quotient, Uint32Constant(divisor)));
939 1174 : node->TrimInputCount(2);
940 1174 : NodeProperties::ChangeOp(node, machine()->Int32Sub());
941 : }
942 : return Changed(node);
943 : }
944 : return NoChange();
945 : }
946 :
947 :
948 2605087 : Reduction MachineOperatorReducer::ReduceStore(Node* node) {
949 : NodeMatcher nm(node);
950 : MachineRepresentation rep;
951 : int value_input;
952 2605087 : if (nm.IsStore()) {
953 2605087 : rep = StoreRepresentationOf(node->op()).representation();
954 : value_input = 2;
955 : } else {
956 : DCHECK(nm.IsUnalignedStore());
957 0 : rep = UnalignedStoreRepresentationOf(node->op());
958 : value_input = 2;
959 : }
960 :
961 2605087 : Node* const value = node->InputAt(value_input);
962 :
963 2605087 : switch (value->opcode()) {
964 : case IrOpcode::kWord32And: {
965 7424 : Uint32BinopMatcher m(value);
966 20046 : if (m.right().HasValue() && ((rep == MachineRepresentation::kWord8 &&
967 7160 : (m.right().Value() & 0xFF) == 0xFF) ||
968 1358 : (rep == MachineRepresentation::kWord16 &&
969 1358 : (m.right().Value() & 0xFFFF) == 0xFFFF))) {
970 6300 : node->ReplaceInput(value_input, m.left().node());
971 6300 : return Changed(node);
972 : }
973 1124 : break;
974 : }
975 : case IrOpcode::kWord32Sar: {
976 431 : Int32BinopMatcher m(value);
977 1012 : if (m.left().IsWord32Shl() && ((rep == MachineRepresentation::kWord8 &&
978 234 : m.right().IsInRange(1, 24)) ||
979 226 : (rep == MachineRepresentation::kWord16 &&
980 : m.right().IsInRange(1, 16)))) {
981 376 : Int32BinopMatcher mleft(m.left().node());
982 376 : if (mleft.right().Is(m.right().Value())) {
983 376 : node->ReplaceInput(value_input, mleft.left().node());
984 376 : return Changed(node);
985 : }
986 : }
987 55 : break;
988 : }
989 : default:
990 : break;
991 : }
992 : return NoChange();
993 : }
994 :
995 :
996 249990 : Reduction MachineOperatorReducer::ReduceProjection(size_t index, Node* node) {
997 249990 : switch (node->opcode()) {
998 : case IrOpcode::kInt32AddWithOverflow: {
999 : DCHECK(index == 0 || index == 1);
1000 148041 : Int32BinopMatcher m(node);
1001 148040 : if (m.IsFoldable()) {
1002 : int32_t val;
1003 : bool ovf = base::bits::SignedAddOverflow32(m.left().Value(),
1004 20006 : m.right().Value(), &val);
1005 20006 : return ReplaceInt32(index == 0 ? val : ovf);
1006 : }
1007 128034 : if (m.right().Is(0)) {
1008 32 : return Replace(index == 0 ? m.left().node() : m.right().node());
1009 : }
1010 128002 : break;
1011 : }
1012 : case IrOpcode::kInt32SubWithOverflow: {
1013 : DCHECK(index == 0 || index == 1);
1014 44773 : Int32BinopMatcher m(node);
1015 44773 : if (m.IsFoldable()) {
1016 : int32_t val;
1017 : bool ovf = base::bits::SignedSubOverflow32(m.left().Value(),
1018 20056 : m.right().Value(), &val);
1019 20056 : return ReplaceInt32(index == 0 ? val : ovf);
1020 : }
1021 24717 : if (m.right().Is(0)) {
1022 2 : return Replace(index == 0 ? m.left().node() : m.right().node());
1023 : }
1024 24715 : break;
1025 : }
1026 : case IrOpcode::kInt32MulWithOverflow: {
1027 : DCHECK(index == 0 || index == 1);
1028 27576 : Int32BinopMatcher m(node);
1029 27576 : if (m.IsFoldable()) {
1030 : int32_t val;
1031 : bool ovf = base::bits::SignedMulOverflow32(m.left().Value(),
1032 20312 : m.right().Value(), &val);
1033 20312 : return ReplaceInt32(index == 0 ? val : ovf);
1034 : }
1035 7264 : if (m.right().Is(0)) {
1036 : return Replace(m.right().node());
1037 : }
1038 7176 : if (m.right().Is(1)) {
1039 42 : return index == 0 ? Replace(m.left().node()) : ReplaceInt32(0);
1040 : }
1041 7134 : break;
1042 : }
1043 : default:
1044 : break;
1045 : }
1046 : return NoChange();
1047 : }
1048 :
1049 :
1050 110331 : Reduction MachineOperatorReducer::ReduceWord32Shifts(Node* node) {
1051 : DCHECK((node->opcode() == IrOpcode::kWord32Shl) ||
1052 : (node->opcode() == IrOpcode::kWord32Shr) ||
1053 : (node->opcode() == IrOpcode::kWord32Sar));
1054 110331 : if (machine()->Word32ShiftIsSafe()) {
1055 : // Remove the explicit 'and' with 0x1F if the shift provided by the machine
1056 : // instruction matches that required by JavaScript.
1057 110016 : Int32BinopMatcher m(node);
1058 110016 : if (m.right().IsWord32And()) {
1059 2192 : Int32BinopMatcher mright(m.right().node());
1060 2192 : if (mright.right().Is(0x1F)) {
1061 1004 : node->ReplaceInput(1, mright.left().node());
1062 1004 : return Changed(node);
1063 : }
1064 : }
1065 : }
1066 : return NoChange();
1067 : }
1068 :
1069 :
1070 47446 : Reduction MachineOperatorReducer::ReduceWord32Shl(Node* node) {
1071 : DCHECK_EQ(IrOpcode::kWord32Shl, node->opcode());
1072 47446 : Int32BinopMatcher m(node);
1073 47446 : if (m.right().Is(0)) return Replace(m.left().node()); // x << 0 => x
1074 46745 : if (m.IsFoldable()) { // K << K => K
1075 : return ReplaceInt32(
1076 14175 : base::ShlWithWraparound(m.left().Value(), m.right().Value()));
1077 : }
1078 32570 : if (m.right().IsInRange(1, 31)) {
1079 : // (x >>> K) << K => x & ~(2^K - 1)
1080 : // (x >> K) << K => x & ~(2^K - 1)
1081 28904 : if (m.left().IsWord32Sar() || m.left().IsWord32Shr()) {
1082 4134 : Int32BinopMatcher mleft(m.left().node());
1083 4134 : if (mleft.right().Is(m.right().Value())) {
1084 3069 : node->ReplaceInput(0, mleft.left().node());
1085 : node->ReplaceInput(1,
1086 6138 : Uint32Constant(~((1U << m.right().Value()) - 1U)));
1087 3069 : NodeProperties::ChangeOp(node, machine()->Word32And());
1088 3069 : Reduction reduction = ReduceWord32And(node);
1089 3069 : return reduction.Changed() ? reduction : Changed(node);
1090 : }
1091 : }
1092 : }
1093 29501 : return ReduceWord32Shifts(node);
1094 : }
1095 :
1096 618246 : Reduction MachineOperatorReducer::ReduceWord64Shl(Node* node) {
1097 : DCHECK_EQ(IrOpcode::kWord64Shl, node->opcode());
1098 618246 : Int64BinopMatcher m(node);
1099 618247 : if (m.right().Is(0)) return Replace(m.left().node()); // x << 0 => x
1100 617837 : if (m.IsFoldable()) { // K << K => K
1101 : return ReplaceInt64(
1102 86226 : base::ShlWithWraparound(m.left().Value(), m.right().Value()));
1103 : }
1104 : return NoChange();
1105 : }
1106 :
1107 85655 : Reduction MachineOperatorReducer::ReduceWord32Shr(Node* node) {
1108 85655 : Uint32BinopMatcher m(node);
1109 85655 : if (m.right().Is(0)) return Replace(m.left().node()); // x >>> 0 => x
1110 70547 : if (m.IsFoldable()) { // K >>> K => K
1111 9991 : return ReplaceInt32(m.left().Value() >> (m.right().Value() & 31));
1112 : }
1113 60556 : if (m.left().IsWord32And() && m.right().HasValue()) {
1114 27905 : Uint32BinopMatcher mleft(m.left().node());
1115 27905 : if (mleft.right().HasValue()) {
1116 27902 : uint32_t shift = m.right().Value() & 31;
1117 27902 : uint32_t mask = mleft.right().Value();
1118 27902 : if ((mask >> shift) == 0) {
1119 : // (m >>> s) == 0 implies ((x & m) >>> s) == 0
1120 31 : return ReplaceInt32(0);
1121 : }
1122 : }
1123 : }
1124 60525 : return ReduceWord32Shifts(node);
1125 : }
1126 :
1127 47427 : Reduction MachineOperatorReducer::ReduceWord64Shr(Node* node) {
1128 : DCHECK_EQ(IrOpcode::kWord64Shr, node->opcode());
1129 47427 : Uint64BinopMatcher m(node);
1130 47427 : if (m.right().Is(0)) return Replace(m.left().node()); // x >>> 0 => x
1131 47017 : if (m.IsFoldable()) { // K >> K => K
1132 25515 : return ReplaceInt64(m.left().Value() >> (m.right().Value() & 63));
1133 : }
1134 : return NoChange();
1135 : }
1136 :
1137 31414 : Reduction MachineOperatorReducer::ReduceWord32Sar(Node* node) {
1138 31414 : Int32BinopMatcher m(node);
1139 31414 : if (m.right().Is(0)) return Replace(m.left().node()); // x >> 0 => x
1140 30595 : if (m.IsFoldable()) { // K >> K => K
1141 10233 : return ReplaceInt32(m.left().Value() >> (m.right().Value() & 31));
1142 : }
1143 20362 : if (m.left().IsWord32Shl()) {
1144 1457 : Int32BinopMatcher mleft(m.left().node());
1145 1457 : if (mleft.left().IsComparison()) {
1146 110 : if (m.right().Is(31) && mleft.right().Is(31)) {
1147 : // Comparison << 31 >> 31 => 0 - Comparison
1148 55 : node->ReplaceInput(0, Int32Constant(0));
1149 55 : node->ReplaceInput(1, mleft.left().node());
1150 55 : NodeProperties::ChangeOp(node, machine()->Int32Sub());
1151 55 : Reduction const reduction = ReduceInt32Sub(node);
1152 55 : return reduction.Changed() ? reduction : Changed(node);
1153 : }
1154 1402 : } else if (mleft.left().IsLoad()) {
1155 : LoadRepresentation const rep =
1156 2 : LoadRepresentationOf(mleft.left().node()->op());
1157 4 : if (m.right().Is(24) && mleft.right().Is(24) &&
1158 : rep == MachineType::Int8()) {
1159 : // Load[kMachInt8] << 24 >> 24 => Load[kMachInt8]
1160 : return Replace(mleft.left().node());
1161 : }
1162 3 : if (m.right().Is(16) && mleft.right().Is(16) &&
1163 : rep == MachineType::Int16()) {
1164 : // Load[kMachInt16] << 16 >> 16 => Load[kMachInt8]
1165 : return Replace(mleft.left().node());
1166 : }
1167 : }
1168 : }
1169 20305 : return ReduceWord32Shifts(node);
1170 : }
1171 :
1172 343643 : Reduction MachineOperatorReducer::ReduceWord64Sar(Node* node) {
1173 343643 : Int64BinopMatcher m(node);
1174 343643 : if (m.right().Is(0)) return Replace(m.left().node()); // x >> 0 => x
1175 343233 : if (m.IsFoldable()) {
1176 32310 : return ReplaceInt64(m.left().Value() >> (m.right().Value() & 63));
1177 : }
1178 : return NoChange();
1179 : }
1180 :
1181 652639 : Reduction MachineOperatorReducer::ReduceWord32And(Node* node) {
1182 : DCHECK_EQ(IrOpcode::kWord32And, node->opcode());
1183 652639 : Int32BinopMatcher m(node);
1184 652640 : if (m.right().Is(0)) return Replace(m.right().node()); // x & 0 => 0
1185 650729 : if (m.right().Is(-1)) return Replace(m.left().node()); // x & -1 => x
1186 651560 : if (m.left().IsComparison() && m.right().Is(1)) { // CMP & 1 => CMP
1187 : return Replace(m.left().node());
1188 : }
1189 650036 : if (m.IsFoldable()) { // K & K => K
1190 28901 : return ReplaceInt32(m.left().Value() & m.right().Value());
1191 : }
1192 621135 : if (m.LeftEqualsRight()) return Replace(m.left().node()); // x & x => x
1193 621014 : if (m.left().IsWord32And() && m.right().HasValue()) {
1194 23095 : Int32BinopMatcher mleft(m.left().node());
1195 23095 : if (mleft.right().HasValue()) { // (x & K) & K => x & K
1196 19731 : node->ReplaceInput(0, mleft.left().node());
1197 : node->ReplaceInput(
1198 39462 : 1, Int32Constant(m.right().Value() & mleft.right().Value()));
1199 19731 : Reduction const reduction = ReduceWord32And(node);
1200 19731 : return reduction.Changed() ? reduction : Changed(node);
1201 : }
1202 : }
1203 601283 : if (m.right().IsNegativePowerOf2()) {
1204 292275 : int32_t const mask = m.right().Value();
1205 : int32_t const neg_mask = base::NegateWithWraparound(mask);
1206 292275 : if (m.left().IsWord32Shl()) {
1207 2360 : Uint32BinopMatcher mleft(m.left().node());
1208 4720 : if (mleft.right().HasValue() &&
1209 2360 : (mleft.right().Value() & 0x1F) >=
1210 : base::bits::CountTrailingZeros(mask)) {
1211 : // (x << L) & (-1 << K) => x << L iff L >= K
1212 2358 : return Replace(mleft.node());
1213 : }
1214 289915 : } else if (m.left().IsInt32Add()) {
1215 109411 : Int32BinopMatcher mleft(m.left().node());
1216 196091 : if (mleft.right().HasValue() &&
1217 86680 : (mleft.right().Value() & mask) == mleft.right().Value()) {
1218 : // (x + (K << L)) & (-1 << L) => (x & (-1 << L)) + (K << L)
1219 86467 : node->ReplaceInput(0, Word32And(mleft.left().node(), m.right().node()));
1220 86467 : node->ReplaceInput(1, mleft.right().node());
1221 86467 : NodeProperties::ChangeOp(node, machine()->Int32Add());
1222 86467 : Reduction const reduction = ReduceInt32Add(node);
1223 86467 : return reduction.Changed() ? reduction : Changed(node);
1224 : }
1225 22944 : if (mleft.left().IsInt32Mul()) {
1226 2924 : Int32BinopMatcher mleftleft(mleft.left().node());
1227 2924 : if (mleftleft.right().IsMultipleOf(neg_mask)) {
1228 : // (y * (K << L) + x) & (-1 << L) => (x & (-1 << L)) + y * (K << L)
1229 : node->ReplaceInput(0,
1230 2923 : Word32And(mleft.right().node(), m.right().node()));
1231 2923 : node->ReplaceInput(1, mleftleft.node());
1232 2923 : NodeProperties::ChangeOp(node, machine()->Int32Add());
1233 2923 : Reduction const reduction = ReduceInt32Add(node);
1234 2923 : return reduction.Changed() ? reduction : Changed(node);
1235 : }
1236 : }
1237 20021 : if (mleft.right().IsInt32Mul()) {
1238 7975 : Int32BinopMatcher mleftright(mleft.right().node());
1239 7975 : if (mleftright.right().IsMultipleOf(neg_mask)) {
1240 : // (x + y * (K << L)) & (-1 << L) => (x & (-1 << L)) + y * (K << L)
1241 : node->ReplaceInput(0,
1242 7963 : Word32And(mleft.left().node(), m.right().node()));
1243 7963 : node->ReplaceInput(1, mleftright.node());
1244 7963 : NodeProperties::ChangeOp(node, machine()->Int32Add());
1245 7963 : Reduction const reduction = ReduceInt32Add(node);
1246 7963 : return reduction.Changed() ? reduction : Changed(node);
1247 : }
1248 : }
1249 12058 : if (mleft.left().IsWord32Shl()) {
1250 37 : Int32BinopMatcher mleftleft(mleft.left().node());
1251 74 : if (mleftleft.right().Is(base::bits::CountTrailingZeros(mask))) {
1252 : // (y << L + x) & (-1 << L) => (x & (-1 << L)) + y << L
1253 : node->ReplaceInput(0,
1254 31 : Word32And(mleft.right().node(), m.right().node()));
1255 31 : node->ReplaceInput(1, mleftleft.node());
1256 31 : NodeProperties::ChangeOp(node, machine()->Int32Add());
1257 31 : Reduction const reduction = ReduceInt32Add(node);
1258 31 : return reduction.Changed() ? reduction : Changed(node);
1259 : }
1260 : }
1261 12027 : if (mleft.right().IsWord32Shl()) {
1262 7515 : Int32BinopMatcher mleftright(mleft.right().node());
1263 15030 : if (mleftright.right().Is(base::bits::CountTrailingZeros(mask))) {
1264 : // (x + y << L) & (-1 << L) => (x & (-1 << L)) + y << L
1265 : node->ReplaceInput(0,
1266 2856 : Word32And(mleft.left().node(), m.right().node()));
1267 2856 : node->ReplaceInput(1, mleftright.node());
1268 2856 : NodeProperties::ChangeOp(node, machine()->Int32Add());
1269 2856 : Reduction const reduction = ReduceInt32Add(node);
1270 2856 : return reduction.Changed() ? reduction : Changed(node);
1271 : }
1272 : }
1273 180504 : } else if (m.left().IsInt32Mul()) {
1274 5898 : Int32BinopMatcher mleft(m.left().node());
1275 5898 : if (mleft.right().IsMultipleOf(neg_mask)) {
1276 : // (x * (K << L)) & (-1 << L) => x * (K << L)
1277 5898 : return Replace(mleft.node());
1278 : }
1279 : }
1280 : }
1281 : return NoChange();
1282 : }
1283 :
1284 47484 : Reduction MachineOperatorReducer::TryMatchWord32Ror(Node* node) {
1285 : DCHECK(IrOpcode::kWord32Or == node->opcode() ||
1286 : IrOpcode::kWord32Xor == node->opcode());
1287 47484 : Int32BinopMatcher m(node);
1288 : Node* shl = nullptr;
1289 : Node* shr = nullptr;
1290 : // Recognize rotation, we are matching:
1291 : // * x << y | x >>> (32 - y) => x ror (32 - y), i.e x rol y
1292 : // * x << (32 - y) | x >>> y => x ror y
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 : // as well as their commuted form.
1296 53130 : if (m.left().IsWord32Shl() && m.right().IsWord32Shr()) {
1297 : shl = m.left().node();
1298 : shr = m.right().node();
1299 47013 : } else if (m.left().IsWord32Shr() && m.right().IsWord32Shl()) {
1300 : shl = m.right().node();
1301 : shr = m.left().node();
1302 : } else {
1303 : return NoChange();
1304 : }
1305 :
1306 880 : Int32BinopMatcher mshl(shl);
1307 880 : Int32BinopMatcher mshr(shr);
1308 880 : if (mshl.left().node() != mshr.left().node()) return NoChange();
1309 :
1310 577 : if (mshl.right().HasValue() && mshr.right().HasValue()) {
1311 : // Case where y is a constant.
1312 382 : if (mshl.right().Value() + mshr.right().Value() != 32) return NoChange();
1313 : } else {
1314 : Node* sub = nullptr;
1315 : Node* y = nullptr;
1316 195 : if (mshl.right().IsInt32Sub()) {
1317 : sub = mshl.right().node();
1318 : y = mshr.right().node();
1319 158 : } else if (mshr.right().IsInt32Sub()) {
1320 : sub = mshr.right().node();
1321 : y = mshl.right().node();
1322 : } else {
1323 128 : return NoChange();
1324 : }
1325 :
1326 109 : Int32BinopMatcher msub(sub);
1327 218 : if (!msub.left().Is(32) || msub.right().node() != y) return NoChange();
1328 : }
1329 :
1330 449 : node->ReplaceInput(0, mshl.left().node());
1331 449 : node->ReplaceInput(1, mshr.right().node());
1332 449 : NodeProperties::ChangeOp(node, machine()->Word32Ror());
1333 : return Changed(node);
1334 : }
1335 :
1336 76233 : Reduction MachineOperatorReducer::ReduceWord32Or(Node* node) {
1337 : DCHECK_EQ(IrOpcode::kWord32Or, node->opcode());
1338 76233 : Int32BinopMatcher m(node);
1339 76233 : if (m.right().Is(0)) return Replace(m.left().node()); // x | 0 => x
1340 62483 : if (m.right().Is(-1)) return Replace(m.right().node()); // x | -1 => -1
1341 59069 : if (m.IsFoldable()) { // K | K => K
1342 17383 : return ReplaceInt32(m.left().Value() | m.right().Value());
1343 : }
1344 41686 : if (m.LeftEqualsRight()) return Replace(m.left().node()); // x | x => x
1345 :
1346 41634 : return TryMatchWord32Ror(node);
1347 : }
1348 :
1349 24089 : Reduction MachineOperatorReducer::ReduceWord32Xor(Node* node) {
1350 : DCHECK_EQ(IrOpcode::kWord32Xor, node->opcode());
1351 24089 : Int32BinopMatcher m(node);
1352 24089 : if (m.right().Is(0)) return Replace(m.left().node()); // x ^ 0 => x
1353 23536 : if (m.IsFoldable()) { // K ^ K => K
1354 17661 : return ReplaceInt32(m.left().Value() ^ m.right().Value());
1355 : }
1356 5875 : if (m.LeftEqualsRight()) return ReplaceInt32(0); // x ^ x => 0
1357 6071 : if (m.left().IsWord32Xor() && m.right().Is(-1)) {
1358 11 : Int32BinopMatcher mleft(m.left().node());
1359 11 : if (mleft.right().Is(-1)) { // (x ^ -1) ^ -1 => x
1360 11 : return Replace(mleft.left().node());
1361 : }
1362 : }
1363 :
1364 5850 : return TryMatchWord32Ror(node);
1365 : }
1366 :
1367 4856 : Reduction MachineOperatorReducer::ReduceFloat64InsertLowWord32(Node* node) {
1368 : DCHECK_EQ(IrOpcode::kFloat64InsertLowWord32, node->opcode());
1369 : Float64Matcher mlhs(node->InputAt(0));
1370 : Uint32Matcher mrhs(node->InputAt(1));
1371 4856 : if (mlhs.HasValue() && mrhs.HasValue()) {
1372 : return ReplaceFloat64(bit_cast<double>(
1373 4800 : (bit_cast<uint64_t>(mlhs.Value()) & uint64_t{0xFFFFFFFF00000000}) |
1374 : mrhs.Value()));
1375 : }
1376 : return NoChange();
1377 : }
1378 :
1379 :
1380 4856 : Reduction MachineOperatorReducer::ReduceFloat64InsertHighWord32(Node* node) {
1381 : DCHECK_EQ(IrOpcode::kFloat64InsertHighWord32, node->opcode());
1382 : Float64Matcher mlhs(node->InputAt(0));
1383 : Uint32Matcher mrhs(node->InputAt(1));
1384 4856 : if (mlhs.HasValue() && mrhs.HasValue()) {
1385 : return ReplaceFloat64(bit_cast<double>(
1386 9600 : (bit_cast<uint64_t>(mlhs.Value()) & uint64_t{0xFFFFFFFF}) |
1387 4800 : (static_cast<uint64_t>(mrhs.Value()) << 32)));
1388 : }
1389 : return NoChange();
1390 : }
1391 :
1392 :
1393 : namespace {
1394 :
1395 : bool IsFloat64RepresentableAsFloat32(const Float64Matcher& m) {
1396 197025 : if (m.HasValue()) {
1397 51689 : double v = m.Value();
1398 51689 : float fv = static_cast<float>(v);
1399 51689 : return static_cast<double>(fv) == v;
1400 : }
1401 : return false;
1402 : }
1403 :
1404 : } // namespace
1405 :
1406 :
1407 264178 : Reduction MachineOperatorReducer::ReduceFloat64Compare(Node* node) {
1408 : DCHECK(IrOpcode::kFloat64Equal == node->opcode() ||
1409 : IrOpcode::kFloat64LessThan == node->opcode() ||
1410 : IrOpcode::kFloat64LessThanOrEqual == node->opcode());
1411 230071 : Float64BinopMatcher m(node);
1412 230072 : if (m.IsFoldable()) {
1413 32870 : switch (node->opcode()) {
1414 : case IrOpcode::kFloat64Equal:
1415 11924 : return ReplaceBool(m.left().Value() == m.right().Value());
1416 : case IrOpcode::kFloat64LessThan:
1417 10758 : return ReplaceBool(m.left().Value() < m.right().Value());
1418 : case IrOpcode::kFloat64LessThanOrEqual:
1419 10188 : return ReplaceBool(m.left().Value() <= m.right().Value());
1420 : default:
1421 0 : UNREACHABLE();
1422 : }
1423 198619 : } else if ((m.left().IsChangeFloat32ToFloat64() &&
1424 196597 : m.right().IsChangeFloat32ToFloat64()) ||
1425 812 : (m.left().IsChangeFloat32ToFloat64() &&
1426 393415 : IsFloat64RepresentableAsFloat32(m.right())) ||
1427 51214 : (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 1237 : switch (node->opcode()) {
1435 : case IrOpcode::kFloat64Equal:
1436 303 : NodeProperties::ChangeOp(node, machine()->Float32Equal());
1437 303 : break;
1438 : case IrOpcode::kFloat64LessThan:
1439 647 : NodeProperties::ChangeOp(node, machine()->Float32LessThan());
1440 647 : break;
1441 : case IrOpcode::kFloat64LessThanOrEqual:
1442 287 : NodeProperties::ChangeOp(node, machine()->Float32LessThanOrEqual());
1443 287 : break;
1444 : default:
1445 0 : UNREACHABLE();
1446 : }
1447 : node->ReplaceInput(
1448 1237 : 0, m.left().HasValue()
1449 248 : ? Float32Constant(static_cast<float>(m.left().Value()))
1450 2722 : : m.left().InputAt(0));
1451 : node->ReplaceInput(
1452 1237 : 1, m.right().HasValue()
1453 384 : ? Float32Constant(static_cast<float>(m.right().Value()))
1454 2858 : : m.right().InputAt(0));
1455 : return Changed(node);
1456 : }
1457 : return NoChange();
1458 : }
1459 :
1460 53217 : Reduction MachineOperatorReducer::ReduceFloat64RoundDown(Node* node) {
1461 : DCHECK_EQ(IrOpcode::kFloat64RoundDown, node->opcode());
1462 : Float64Matcher m(node->InputAt(0));
1463 53217 : if (m.HasValue()) {
1464 : return ReplaceFloat64(Floor(m.Value()));
1465 : }
1466 : return NoChange();
1467 : }
1468 :
1469 614720 : CommonOperatorBuilder* MachineOperatorReducer::common() const {
1470 614720 : return mcgraph()->common();
1471 : }
1472 :
1473 :
1474 666033 : MachineOperatorBuilder* MachineOperatorReducer::machine() const {
1475 666033 : return mcgraph()->machine();
1476 : }
1477 :
1478 750846 : Graph* MachineOperatorReducer::graph() const { return mcgraph()->graph(); }
1479 :
1480 : } // namespace compiler
1481 : } // namespace internal
1482 183867 : } // namespace v8
|