5 #include "src/compiler/machine-operator-reducer.h" 7 #include "src/base/bits.h" 8 #include "src/base/division-by-constant.h" 9 #include "src/base/ieee754.h" 10 #include "src/compiler/diamond.h" 11 #include "src/compiler/graph.h" 12 #include "src/compiler/machine-graph.h" 13 #include "src/compiler/node-matchers.h" 14 #include "src/compiler/node-properties.h" 15 #include "src/conversions-inl.h" 21 MachineOperatorReducer::MachineOperatorReducer(MachineGraph* mcgraph,
22 bool allow_signalling_nan)
23 : mcgraph_(mcgraph), allow_signalling_nan_(allow_signalling_nan) {}
25 MachineOperatorReducer::~MachineOperatorReducer() =
default;
28 Node* MachineOperatorReducer::Float32Constant(
volatile float value) {
29 return graph()->NewNode(common()->Float32Constant(value));
33 Node* MachineOperatorReducer::Float64Constant(
volatile double value) {
34 return mcgraph()->Float64Constant(value);
38 Node* MachineOperatorReducer::Int32Constant(int32_t value) {
39 return mcgraph()->Int32Constant(value);
43 Node* MachineOperatorReducer::Int64Constant(
int64_t value) {
44 return graph()->NewNode(common()->Int64Constant(value));
47 Node* MachineOperatorReducer::Float64Mul(Node* lhs, Node* rhs) {
48 return graph()->NewNode(machine()->Float64Mul(), lhs, rhs);
51 Node* MachineOperatorReducer::Float64PowHalf(Node* value) {
53 graph()->NewNode(machine()->Float64Add(), Float64Constant(0.0), value);
54 Diamond d(graph(), common(),
55 graph()->NewNode(machine()->Float64LessThanOrEqual(), value,
56 Float64Constant(-V8_INFINITY)),
58 return d.Phi(MachineRepresentation::kFloat64, Float64Constant(V8_INFINITY),
59 graph()->NewNode(machine()->Float64Sqrt(), value));
62 Node* MachineOperatorReducer::Word32And(Node* lhs, Node* rhs) {
63 Node*
const node = graph()->NewNode(machine()->Word32And(), lhs, rhs);
64 Reduction
const reduction = ReduceWord32And(node);
65 return reduction.Changed() ? reduction.replacement() : node;
69 Node* MachineOperatorReducer::Word32Sar(Node* lhs,
uint32_t rhs) {
70 if (rhs == 0)
return lhs;
71 return graph()->NewNode(machine()->Word32Sar(), lhs, Uint32Constant(rhs));
75 Node* MachineOperatorReducer::Word32Shr(Node* lhs,
uint32_t rhs) {
76 if (rhs == 0)
return lhs;
77 return graph()->NewNode(machine()->Word32Shr(), lhs, Uint32Constant(rhs));
81 Node* MachineOperatorReducer::Word32Equal(Node* lhs, Node* rhs) {
82 return graph()->NewNode(machine()->Word32Equal(), lhs, rhs);
86 Node* MachineOperatorReducer::Int32Add(Node* lhs, Node* rhs) {
87 Node*
const node = graph()->NewNode(machine()->Int32Add(), lhs, rhs);
88 Reduction
const reduction = ReduceInt32Add(node);
89 return reduction.Changed() ? reduction.replacement() : node;
93 Node* MachineOperatorReducer::Int32Sub(Node* lhs, Node* rhs) {
94 Node*
const node = graph()->NewNode(machine()->Int32Sub(), lhs, rhs);
95 Reduction
const reduction = ReduceInt32Sub(node);
96 return reduction.Changed() ? reduction.replacement() : node;
100 Node* MachineOperatorReducer::Int32Mul(Node* lhs, Node* rhs) {
101 return graph()->NewNode(machine()->Int32Mul(), lhs, rhs);
105 Node* MachineOperatorReducer::Int32Div(Node* dividend, int32_t divisor) {
106 DCHECK_NE(0, divisor);
107 DCHECK_NE(std::numeric_limits<int32_t>::min(), divisor);
108 base::MagicNumbersForDivision<uint32_t>
const mag =
109 base::SignedDivisionByConstant(bit_cast<uint32_t>(divisor));
110 Node* quotient = graph()->NewNode(machine()->Int32MulHigh(), dividend,
111 Uint32Constant(mag.multiplier));
112 if (divisor > 0 && bit_cast<int32_t>(mag.multiplier) < 0) {
113 quotient = Int32Add(quotient, dividend);
114 }
else if (divisor < 0 && bit_cast<int32_t>(mag.multiplier) > 0) {
115 quotient = Int32Sub(quotient, dividend);
117 return Int32Add(Word32Sar(quotient, mag.shift), Word32Shr(dividend, 31));
121 Node* MachineOperatorReducer::Uint32Div(Node* dividend,
uint32_t divisor) {
122 DCHECK_LT(0u, divisor);
125 unsigned const shift = base::bits::CountTrailingZeros(divisor);
126 dividend = Word32Shr(dividend, shift);
129 base::MagicNumbersForDivision<uint32_t>
const mag =
130 base::UnsignedDivisionByConstant(divisor, shift);
131 Node* quotient = graph()->NewNode(machine()->Uint32MulHigh(), dividend,
132 Uint32Constant(mag.multiplier));
134 DCHECK_LE(1u, mag.shift);
135 quotient = Word32Shr(
136 Int32Add(Word32Shr(Int32Sub(dividend, quotient), 1), quotient),
139 quotient = Word32Shr(quotient, mag.shift);
146 Reduction MachineOperatorReducer::Reduce(Node* node) {
147 switch (node->opcode()) {
148 case IrOpcode::kProjection:
149 return ReduceProjection(ProjectionIndexOf(node->op()), node->InputAt(0));
150 case IrOpcode::kWord32And:
151 return ReduceWord32And(node);
152 case IrOpcode::kWord32Or:
153 return ReduceWord32Or(node);
154 case IrOpcode::kWord32Xor:
155 return ReduceWord32Xor(node);
156 case IrOpcode::kWord32Shl:
157 return ReduceWord32Shl(node);
158 case IrOpcode::kWord64Shl:
159 return ReduceWord64Shl(node);
160 case IrOpcode::kWord32Shr:
161 return ReduceWord32Shr(node);
162 case IrOpcode::kWord64Shr:
163 return ReduceWord64Shr(node);
164 case IrOpcode::kWord32Sar:
165 return ReduceWord32Sar(node);
166 case IrOpcode::kWord64Sar:
167 return ReduceWord64Sar(node);
168 case IrOpcode::kWord32Ror: {
169 Int32BinopMatcher m(node);
170 if (m.right().Is(0))
return Replace(m.left().node());
171 if (m.IsFoldable()) {
173 base::bits::RotateRight32(m.left().Value(), m.right().Value()));
177 case IrOpcode::kWord32Equal: {
178 Int32BinopMatcher m(node);
179 if (m.IsFoldable()) {
180 return ReplaceBool(m.left().Value() == m.right().Value());
182 if (m.left().IsInt32Sub() && m.right().Is(0)) {
183 Int32BinopMatcher msub(m.left().node());
184 node->ReplaceInput(0, msub.left().node());
185 node->ReplaceInput(1, msub.right().node());
186 return Changed(node);
189 if (m.LeftEqualsRight())
return ReplaceBool(
true);
192 case IrOpcode::kWord64Equal: {
193 Int64BinopMatcher m(node);
194 if (m.IsFoldable()) {
195 return ReplaceBool(m.left().Value() == m.right().Value());
197 if (m.left().IsInt64Sub() && m.right().Is(0)) {
198 Int64BinopMatcher msub(m.left().node());
199 node->ReplaceInput(0, msub.left().node());
200 node->ReplaceInput(1, msub.right().node());
201 return Changed(node);
204 if (m.LeftEqualsRight())
return ReplaceBool(
true);
207 case IrOpcode::kInt32Add:
208 return ReduceInt32Add(node);
209 case IrOpcode::kInt64Add:
210 return ReduceInt64Add(node);
211 case IrOpcode::kInt32Sub:
212 return ReduceInt32Sub(node);
213 case IrOpcode::kInt64Sub:
214 return ReduceInt64Sub(node);
215 case IrOpcode::kInt32Mul: {
216 Int32BinopMatcher m(node);
217 if (m.right().Is(0))
return Replace(m.right().node());
218 if (m.right().Is(1))
return Replace(m.left().node());
219 if (m.IsFoldable()) {
220 return ReplaceInt32(m.left().Value() * m.right().Value());
222 if (m.right().Is(-1)) {
223 node->ReplaceInput(0, Int32Constant(0));
224 node->ReplaceInput(1, m.left().node());
225 NodeProperties::ChangeOp(node, machine()->Int32Sub());
226 return Changed(node);
228 if (m.right().IsPowerOf2()) {
229 node->ReplaceInput(1, Int32Constant(WhichPowerOf2(m.right().Value())));
230 NodeProperties::ChangeOp(node, machine()->Word32Shl());
231 Reduction reduction = ReduceWord32Shl(node);
232 return reduction.Changed() ? reduction : Changed(node);
236 case IrOpcode::kInt32MulWithOverflow: {
237 Int32BinopMatcher m(node);
238 if (m.right().Is(2)) {
239 node->ReplaceInput(1, m.left().node());
240 NodeProperties::ChangeOp(node, machine()->Int32AddWithOverflow());
241 return Changed(node);
243 if (m.right().Is(-1)) {
244 node->ReplaceInput(0, Int32Constant(0));
245 node->ReplaceInput(1, m.left().node());
246 NodeProperties::ChangeOp(node, machine()->Int32SubWithOverflow());
247 return Changed(node);
251 case IrOpcode::kInt32Div:
252 return ReduceInt32Div(node);
253 case IrOpcode::kUint32Div:
254 return ReduceUint32Div(node);
255 case IrOpcode::kInt32Mod:
256 return ReduceInt32Mod(node);
257 case IrOpcode::kUint32Mod:
258 return ReduceUint32Mod(node);
259 case IrOpcode::kInt32LessThan: {
260 Int32BinopMatcher m(node);
261 if (m.IsFoldable()) {
262 return ReplaceBool(m.left().Value() < m.right().Value());
264 if (m.LeftEqualsRight())
return ReplaceBool(
false);
265 if (m.left().IsWord32Or() && m.right().Is(0)) {
267 Int32BinopMatcher mleftmatcher(m.left().node());
268 if (mleftmatcher.left().IsNegative() ||
269 mleftmatcher.right().IsNegative()) {
270 return ReplaceBool(
true);
275 case IrOpcode::kInt32LessThanOrEqual: {
276 Int32BinopMatcher m(node);
277 if (m.IsFoldable()) {
278 return ReplaceBool(m.left().Value() <= m.right().Value());
280 if (m.LeftEqualsRight())
return ReplaceBool(
true);
283 case IrOpcode::kUint32LessThan: {
284 Uint32BinopMatcher m(node);
285 if (m.left().Is(kMaxUInt32))
return ReplaceBool(
false);
286 if (m.right().Is(0))
return ReplaceBool(
false);
287 if (m.IsFoldable()) {
288 return ReplaceBool(m.left().Value() < m.right().Value());
290 if (m.LeftEqualsRight())
return ReplaceBool(
false);
291 if (m.left().IsWord32Sar() && m.right().HasValue()) {
292 Int32BinopMatcher mleft(m.left().node());
293 if (mleft.right().HasValue()) {
296 const uint32_t c = m.right().Value();
297 const uint32_t k = mleft.right().Value() & 0x1F;
298 if (c < static_cast<uint32_t>(kMaxInt >> k)) {
299 node->ReplaceInput(0, mleft.left().node());
300 node->ReplaceInput(1, Uint32Constant(c << k));
301 return Changed(node);
308 case IrOpcode::kUint32LessThanOrEqual: {
309 Uint32BinopMatcher m(node);
310 if (m.left().Is(0))
return ReplaceBool(
true);
311 if (m.right().Is(kMaxUInt32))
return ReplaceBool(
true);
312 if (m.IsFoldable()) {
313 return ReplaceBool(m.left().Value() <= m.right().Value());
315 if (m.LeftEqualsRight())
return ReplaceBool(
true);
318 case IrOpcode::kFloat32Sub: {
319 Float32BinopMatcher m(node);
320 if (allow_signalling_nan_ && m.right().Is(0) &&
321 (copysign(1.0, m.right().Value()) > 0)) {
322 return Replace(m.left().node());
324 if (m.right().IsNaN()) {
326 return ReplaceFloat32(m.right().Value() - m.right().Value());
328 if (m.left().IsNaN()) {
330 return ReplaceFloat32(m.left().Value() - m.left().Value());
332 if (m.IsFoldable()) {
333 return ReplaceFloat32(m.left().Value() - m.right().Value());
335 if (allow_signalling_nan_ && m.left().IsMinusZero()) {
337 if (machine()->Float32RoundUp().IsSupported() &&
338 m.right().IsFloat32RoundDown()) {
339 if (m.right().InputAt(0)->opcode() == IrOpcode::kFloat32Sub) {
340 Float32BinopMatcher mright0(m.right().InputAt(0));
341 if (mright0.left().IsMinusZero()) {
342 return Replace(graph()->NewNode(machine()->Float32RoundUp().op(),
343 mright0.right().node()));
348 node->RemoveInput(0);
349 NodeProperties::ChangeOp(node, machine()->Float32Neg());
350 return Changed(node);
354 case IrOpcode::kFloat64Add: {
355 Float64BinopMatcher m(node);
356 if (m.IsFoldable()) {
357 return ReplaceFloat64(m.left().Value() + m.right().Value());
361 case IrOpcode::kFloat64Sub: {
362 Float64BinopMatcher m(node);
363 if (allow_signalling_nan_ && m.right().Is(0) &&
364 (Double(m.right().Value()).Sign() > 0)) {
365 return Replace(m.left().node());
367 if (m.right().IsNaN()) {
369 return ReplaceFloat64(m.right().Value() - m.right().Value());
371 if (m.left().IsNaN()) {
373 return ReplaceFloat64(m.left().Value() - m.left().Value());
375 if (m.IsFoldable()) {
376 return ReplaceFloat64(m.left().Value() - m.right().Value());
378 if (allow_signalling_nan_ && m.left().IsMinusZero()) {
380 if (machine()->Float64RoundUp().IsSupported() &&
381 m.right().IsFloat64RoundDown()) {
382 if (m.right().InputAt(0)->opcode() == IrOpcode::kFloat64Sub) {
383 Float64BinopMatcher mright0(m.right().InputAt(0));
384 if (mright0.left().IsMinusZero()) {
385 return Replace(graph()->NewNode(machine()->Float64RoundUp().op(),
386 mright0.right().node()));
391 node->RemoveInput(0);
392 NodeProperties::ChangeOp(node, machine()->Float64Neg());
393 return Changed(node);
397 case IrOpcode::kFloat64Mul: {
398 Float64BinopMatcher m(node);
399 if (allow_signalling_nan_ && m.right().Is(1))
400 return Replace(m.left().node());
401 if (m.right().Is(-1)) {
402 node->ReplaceInput(0, Float64Constant(-0.0));
403 node->ReplaceInput(1, m.left().node());
404 NodeProperties::ChangeOp(node, machine()->Float64Sub());
405 return Changed(node);
407 if (m.right().IsNaN()) {
409 return ReplaceFloat64(m.right().Value() - m.right().Value());
411 if (m.IsFoldable()) {
412 return ReplaceFloat64(m.left().Value() * m.right().Value());
414 if (m.right().Is(2)) {
415 node->ReplaceInput(1, m.left().node());
416 NodeProperties::ChangeOp(node, machine()->Float64Add());
417 return Changed(node);
421 case IrOpcode::kFloat64Div: {
422 Float64BinopMatcher m(node);
423 if (allow_signalling_nan_ && m.right().Is(1))
424 return Replace(m.left().node());
426 if (m.right().IsNaN()) {
428 return ReplaceFloat64(m.right().Value() - m.right().Value());
430 if (m.left().IsNaN()) {
432 return ReplaceFloat64(m.left().Value() - m.left().Value());
434 if (m.IsFoldable()) {
435 return ReplaceFloat64(m.left().Value() / m.right().Value());
437 if (allow_signalling_nan_ && m.right().Is(-1)) {
438 node->RemoveInput(1);
439 NodeProperties::ChangeOp(node, machine()->Float64Neg());
440 return Changed(node);
442 if (m.right().IsNormal() && m.right().IsPositiveOrNegativePowerOf2()) {
446 node->ReplaceInput(1, Float64Constant(1.0 / m.right().Value()));
447 NodeProperties::ChangeOp(node, machine()->Float64Mul());
448 return Changed(node);
452 case IrOpcode::kFloat64Mod: {
453 Float64BinopMatcher m(node);
454 if (m.right().Is(0)) {
455 return ReplaceFloat64(std::numeric_limits<double>::quiet_NaN());
457 if (m.right().IsNaN()) {
458 return Replace(m.right().node());
460 if (m.left().IsNaN()) {
461 return Replace(m.left().node());
463 if (m.IsFoldable()) {
464 return ReplaceFloat64(Modulo(m.left().Value(), m.right().Value()));
468 case IrOpcode::kFloat64Acos: {
469 Float64Matcher m(node->InputAt(0));
470 if (m.HasValue())
return ReplaceFloat64(base::ieee754::acos(m.Value()));
473 case IrOpcode::kFloat64Acosh: {
474 Float64Matcher m(node->InputAt(0));
475 if (m.HasValue())
return ReplaceFloat64(base::ieee754::acosh(m.Value()));
478 case IrOpcode::kFloat64Asin: {
479 Float64Matcher m(node->InputAt(0));
480 if (m.HasValue())
return ReplaceFloat64(base::ieee754::asin(m.Value()));
483 case IrOpcode::kFloat64Asinh: {
484 Float64Matcher m(node->InputAt(0));
485 if (m.HasValue())
return ReplaceFloat64(base::ieee754::asinh(m.Value()));
488 case IrOpcode::kFloat64Atan: {
489 Float64Matcher m(node->InputAt(0));
490 if (m.HasValue())
return ReplaceFloat64(base::ieee754::atan(m.Value()));
493 case IrOpcode::kFloat64Atanh: {
494 Float64Matcher m(node->InputAt(0));
495 if (m.HasValue())
return ReplaceFloat64(base::ieee754::atanh(m.Value()));
498 case IrOpcode::kFloat64Atan2: {
499 Float64BinopMatcher m(node);
500 if (m.right().IsNaN()) {
501 return Replace(m.right().node());
503 if (m.left().IsNaN()) {
504 return Replace(m.left().node());
506 if (m.IsFoldable()) {
507 return ReplaceFloat64(
508 base::ieee754::atan2(m.left().Value(), m.right().Value()));
512 case IrOpcode::kFloat64Cbrt: {
513 Float64Matcher m(node->InputAt(0));
514 if (m.HasValue())
return ReplaceFloat64(base::ieee754::cbrt(m.Value()));
517 case IrOpcode::kFloat64Cos: {
518 Float64Matcher m(node->InputAt(0));
519 if (m.HasValue())
return ReplaceFloat64(base::ieee754::cos(m.Value()));
522 case IrOpcode::kFloat64Cosh: {
523 Float64Matcher m(node->InputAt(0));
524 if (m.HasValue())
return ReplaceFloat64(base::ieee754::cosh(m.Value()));
527 case IrOpcode::kFloat64Exp: {
528 Float64Matcher m(node->InputAt(0));
529 if (m.HasValue())
return ReplaceFloat64(base::ieee754::exp(m.Value()));
532 case IrOpcode::kFloat64Expm1: {
533 Float64Matcher m(node->InputAt(0));
534 if (m.HasValue())
return ReplaceFloat64(base::ieee754::expm1(m.Value()));
537 case IrOpcode::kFloat64Log: {
538 Float64Matcher m(node->InputAt(0));
539 if (m.HasValue())
return ReplaceFloat64(base::ieee754::log(m.Value()));
542 case IrOpcode::kFloat64Log1p: {
543 Float64Matcher m(node->InputAt(0));
544 if (m.HasValue())
return ReplaceFloat64(base::ieee754::log1p(m.Value()));
547 case IrOpcode::kFloat64Log10: {
548 Float64Matcher m(node->InputAt(0));
549 if (m.HasValue())
return ReplaceFloat64(base::ieee754::log10(m.Value()));
552 case IrOpcode::kFloat64Log2: {
553 Float64Matcher m(node->InputAt(0));
554 if (m.HasValue())
return ReplaceFloat64(base::ieee754::log2(m.Value()));
557 case IrOpcode::kFloat64Pow: {
558 Float64BinopMatcher m(node);
559 if (m.IsFoldable()) {
560 return ReplaceFloat64(Pow(m.left().Value(), m.right().Value()));
561 }
else if (m.right().Is(0.0)) {
562 return ReplaceFloat64(1.0);
563 }
else if (m.right().Is(-2.0)) {
564 node->ReplaceInput(0, Float64Constant(1.0));
565 node->ReplaceInput(1, Float64Mul(m.left().node(), m.left().node()));
566 NodeProperties::ChangeOp(node, machine()->Float64Div());
567 return Changed(node);
568 }
else if (m.right().Is(2.0)) {
569 node->ReplaceInput(1, m.left().node());
570 NodeProperties::ChangeOp(node, machine()->Float64Mul());
571 return Changed(node);
572 }
else if (m.right().Is(-0.5)) {
574 node->ReplaceInput(0, Float64Constant(1.0));
575 node->ReplaceInput(1, Float64PowHalf(m.left().node()));
576 NodeProperties::ChangeOp(node, machine()->Float64Div());
577 return Changed(node);
578 }
else if (m.right().Is(0.5)) {
580 return Replace(Float64PowHalf(m.left().node()));
584 case IrOpcode::kFloat64Sin: {
585 Float64Matcher m(node->InputAt(0));
586 if (m.HasValue())
return ReplaceFloat64(base::ieee754::sin(m.Value()));
589 case IrOpcode::kFloat64Sinh: {
590 Float64Matcher m(node->InputAt(0));
591 if (m.HasValue())
return ReplaceFloat64(base::ieee754::sinh(m.Value()));
594 case IrOpcode::kFloat64Tan: {
595 Float64Matcher m(node->InputAt(0));
596 if (m.HasValue())
return ReplaceFloat64(base::ieee754::tan(m.Value()));
599 case IrOpcode::kFloat64Tanh: {
600 Float64Matcher m(node->InputAt(0));
601 if (m.HasValue())
return ReplaceFloat64(base::ieee754::tanh(m.Value()));
604 case IrOpcode::kChangeFloat32ToFloat64: {
605 Float32Matcher m(node->InputAt(0));
607 if (!allow_signalling_nan_ && std::isnan(m.Value())) {
609 return ReplaceFloat64(m.Value() + m.Value());
611 return ReplaceFloat64(m.Value());
615 case IrOpcode::kChangeFloat64ToInt32: {
616 Float64Matcher m(node->InputAt(0));
617 if (m.HasValue())
return ReplaceInt32(FastD2IChecked(m.Value()));
618 if (m.IsChangeInt32ToFloat64())
return Replace(m.node()->InputAt(0));
621 case IrOpcode::kChangeFloat64ToInt64: {
622 Float64Matcher m(node->InputAt(0));
623 if (m.HasValue())
return ReplaceInt64(static_cast<int64_t>(m.Value()));
624 if (m.IsChangeInt64ToFloat64())
return Replace(m.node()->InputAt(0));
627 case IrOpcode::kChangeFloat64ToUint32: {
628 Float64Matcher m(node->InputAt(0));
629 if (m.HasValue())
return ReplaceInt32(FastD2UI(m.Value()));
630 if (m.IsChangeUint32ToFloat64())
return Replace(m.node()->InputAt(0));
633 case IrOpcode::kChangeInt32ToFloat64: {
634 Int32Matcher m(node->InputAt(0));
635 if (m.HasValue())
return ReplaceFloat64(FastI2D(m.Value()));
638 case IrOpcode::kChangeInt32ToInt64: {
639 Int32Matcher m(node->InputAt(0));
640 if (m.HasValue())
return ReplaceInt64(m.Value());
643 case IrOpcode::kChangeInt64ToFloat64: {
644 Int64Matcher m(node->InputAt(0));
645 if (m.HasValue())
return ReplaceFloat64(static_cast<double>(m.Value()));
646 if (m.IsChangeFloat64ToInt64())
return Replace(m.node()->InputAt(0));
649 case IrOpcode::kChangeUint32ToFloat64: {
650 Uint32Matcher m(node->InputAt(0));
651 if (m.HasValue())
return ReplaceFloat64(FastUI2D(m.Value()));
654 case IrOpcode::kChangeUint32ToUint64: {
655 Uint32Matcher m(node->InputAt(0));
656 if (m.HasValue())
return ReplaceInt64(static_cast<uint64_t>(m.Value()));
659 case IrOpcode::kTruncateFloat64ToWord32: {
660 Float64Matcher m(node->InputAt(0));
661 if (m.HasValue())
return ReplaceInt32(DoubleToInt32(m.Value()));
662 if (m.IsChangeInt32ToFloat64())
return Replace(m.node()->InputAt(0));
665 case IrOpcode::kTruncateInt64ToInt32: {
666 Int64Matcher m(node->InputAt(0));
667 if (m.HasValue())
return ReplaceInt32(static_cast<int32_t>(m.Value()));
668 if (m.IsChangeInt32ToInt64())
return Replace(m.node()->InputAt(0));
671 case IrOpcode::kTruncateFloat64ToFloat32: {
672 Float64Matcher m(node->InputAt(0));
674 if (!allow_signalling_nan_ && std::isnan(m.Value())) {
676 return ReplaceFloat32(DoubleToFloat32(m.Value() + m.Value()));
678 return ReplaceFloat32(DoubleToFloat32(m.Value()));
680 if (allow_signalling_nan_ && m.IsChangeFloat32ToFloat64())
681 return Replace(m.node()->InputAt(0));
684 case IrOpcode::kRoundFloat64ToInt32: {
685 Float64Matcher m(node->InputAt(0));
687 return ReplaceInt32(DoubleToInt32(m.Value()));
689 if (m.IsChangeInt32ToFloat64())
return Replace(m.node()->InputAt(0));
692 case IrOpcode::kFloat64InsertLowWord32:
693 return ReduceFloat64InsertLowWord32(node);
694 case IrOpcode::kFloat64InsertHighWord32:
695 return ReduceFloat64InsertHighWord32(node);
696 case IrOpcode::kStore:
697 case IrOpcode::kUnalignedStore:
698 return ReduceStore(node);
699 case IrOpcode::kFloat64Equal:
700 case IrOpcode::kFloat64LessThan:
701 case IrOpcode::kFloat64LessThanOrEqual:
702 return ReduceFloat64Compare(node);
703 case IrOpcode::kFloat64RoundDown:
704 return ReduceFloat64RoundDown(node);
711 Reduction MachineOperatorReducer::ReduceInt32Add(Node* node) {
712 DCHECK_EQ(IrOpcode::kInt32Add, node->opcode());
713 Int32BinopMatcher m(node);
714 if (m.right().Is(0))
return Replace(m.left().node());
715 if (m.IsFoldable()) {
716 return ReplaceUint32(bit_cast<uint32_t>(m.left().Value()) +
717 bit_cast<uint32_t>(m.right().Value()));
719 if (m.left().IsInt32Sub()) {
720 Int32BinopMatcher mleft(m.left().node());
721 if (mleft.left().Is(0)) {
722 node->ReplaceInput(0, m.right().node());
723 node->ReplaceInput(1, mleft.right().node());
724 NodeProperties::ChangeOp(node, machine()->Int32Sub());
725 Reduction
const reduction = ReduceInt32Sub(node);
726 return reduction.Changed() ? reduction : Changed(node);
729 if (m.right().IsInt32Sub()) {
730 Int32BinopMatcher mright(m.right().node());
731 if (mright.left().Is(0)) {
732 node->ReplaceInput(1, mright.right().node());
733 NodeProperties::ChangeOp(node, machine()->Int32Sub());
734 Reduction
const reduction = ReduceInt32Sub(node);
735 return reduction.Changed() ? reduction : Changed(node);
741 Reduction MachineOperatorReducer::ReduceInt64Add(Node* node) {
742 DCHECK_EQ(IrOpcode::kInt64Add, node->opcode());
743 Int64BinopMatcher m(node);
744 if (m.right().Is(0))
return Replace(m.left().node());
745 if (m.IsFoldable()) {
746 return Replace(Uint64Constant(bit_cast<uint64_t>(m.left().Value()) +
747 bit_cast<uint64_t>(m.right().Value())));
752 Reduction MachineOperatorReducer::ReduceInt32Sub(Node* node) {
753 DCHECK_EQ(IrOpcode::kInt32Sub, node->opcode());
754 Int32BinopMatcher m(node);
755 if (m.right().Is(0))
return Replace(m.left().node());
756 if (m.IsFoldable()) {
757 return ReplaceInt32(static_cast<uint32_t>(m.left().Value()) -
758 static_cast<uint32_t>(m.right().Value()));
760 if (m.LeftEqualsRight())
return ReplaceInt32(0);
761 if (m.right().HasValue()) {
762 node->ReplaceInput(1, Int32Constant(-m.right().Value()));
763 NodeProperties::ChangeOp(node, machine()->Int32Add());
764 Reduction
const reduction = ReduceInt32Add(node);
765 return reduction.Changed() ? reduction : Changed(node);
770 Reduction MachineOperatorReducer::ReduceInt64Sub(Node* node) {
771 DCHECK_EQ(IrOpcode::kInt64Sub, node->opcode());
772 Int64BinopMatcher m(node);
773 if (m.right().Is(0))
return Replace(m.left().node());
774 if (m.IsFoldable()) {
775 return Replace(Uint64Constant(bit_cast<uint64_t>(m.left().Value()) -
776 bit_cast<uint64_t>(m.right().Value())));
778 if (m.LeftEqualsRight())
return Replace(Int64Constant(0));
779 if (m.right().HasValue()) {
780 node->ReplaceInput(1, Int64Constant(-m.right().Value()));
781 NodeProperties::ChangeOp(node, machine()->Int64Add());
782 Reduction
const reduction = ReduceInt64Add(node);
783 return reduction.Changed() ? reduction : Changed(node);
788 Reduction MachineOperatorReducer::ReduceInt32Div(Node* node) {
789 Int32BinopMatcher m(node);
790 if (m.left().Is(0))
return Replace(m.left().node());
791 if (m.right().Is(0))
return Replace(m.right().node());
792 if (m.right().Is(1))
return Replace(m.left().node());
793 if (m.IsFoldable()) {
795 base::bits::SignedDiv32(m.left().Value(), m.right().Value()));
797 if (m.LeftEqualsRight()) {
798 Node*
const zero = Int32Constant(0);
799 return Replace(Word32Equal(Word32Equal(m.left().node(), zero), zero));
801 if (m.right().Is(-1)) {
802 node->ReplaceInput(0, Int32Constant(0));
803 node->ReplaceInput(1, m.left().node());
804 node->TrimInputCount(2);
805 NodeProperties::ChangeOp(node, machine()->Int32Sub());
806 return Changed(node);
808 if (m.right().HasValue()) {
809 int32_t
const divisor = m.right().Value();
810 Node*
const dividend = m.left().node();
811 Node* quotient = dividend;
812 if (base::bits::IsPowerOfTwo(Abs(divisor))) {
813 uint32_t const shift = WhichPowerOf2(Abs(divisor));
814 DCHECK_NE(0u, shift);
816 quotient = Word32Sar(quotient, 31);
818 quotient = Int32Add(Word32Shr(quotient, 32u - shift), dividend);
819 quotient = Word32Sar(quotient, shift);
821 quotient = Int32Div(quotient, Abs(divisor));
824 node->ReplaceInput(0, Int32Constant(0));
825 node->ReplaceInput(1, quotient);
826 node->TrimInputCount(2);
827 NodeProperties::ChangeOp(node, machine()->Int32Sub());
828 return Changed(node);
830 return Replace(quotient);
836 Reduction MachineOperatorReducer::ReduceUint32Div(Node* node) {
837 Uint32BinopMatcher m(node);
838 if (m.left().Is(0))
return Replace(m.left().node());
839 if (m.right().Is(0))
return Replace(m.right().node());
840 if (m.right().Is(1))
return Replace(m.left().node());
841 if (m.IsFoldable()) {
842 return ReplaceUint32(
843 base::bits::UnsignedDiv32(m.left().Value(), m.right().Value()));
845 if (m.LeftEqualsRight()) {
846 Node*
const zero = Int32Constant(0);
847 return Replace(Word32Equal(Word32Equal(m.left().node(), zero), zero));
849 if (m.right().HasValue()) {
850 Node*
const dividend = m.left().node();
851 uint32_t const divisor = m.right().Value();
852 if (base::bits::IsPowerOfTwo(divisor)) {
853 node->ReplaceInput(1, Uint32Constant(WhichPowerOf2(m.right().Value())));
854 node->TrimInputCount(2);
855 NodeProperties::ChangeOp(node, machine()->Word32Shr());
856 return Changed(node);
858 return Replace(Uint32Div(dividend, divisor));
865 Reduction MachineOperatorReducer::ReduceInt32Mod(Node* node) {
866 Int32BinopMatcher m(node);
867 if (m.left().Is(0))
return Replace(m.left().node());
868 if (m.right().Is(0))
return Replace(m.right().node());
869 if (m.right().Is(1))
return ReplaceInt32(0);
870 if (m.right().Is(-1))
return ReplaceInt32(0);
871 if (m.LeftEqualsRight())
return ReplaceInt32(0);
872 if (m.IsFoldable()) {
874 base::bits::SignedMod32(m.left().Value(), m.right().Value()));
876 if (m.right().HasValue()) {
877 Node*
const dividend = m.left().node();
878 uint32_t const divisor = Abs(m.right().Value());
879 if (base::bits::IsPowerOfTwo(divisor)) {
881 Node*
const zero = Int32Constant(0);
882 Diamond d(graph(), common(),
883 graph()->NewNode(machine()->Int32LessThan(), dividend, zero),
886 d.Phi(MachineRepresentation::kWord32,
887 Int32Sub(zero, Word32And(Int32Sub(zero, dividend), mask)),
888 Word32And(dividend, mask)));
890 Node* quotient = Int32Div(dividend, divisor);
891 DCHECK_EQ(dividend, node->InputAt(0));
892 node->ReplaceInput(1, Int32Mul(quotient, Int32Constant(divisor)));
893 node->TrimInputCount(2);
894 NodeProperties::ChangeOp(node, machine()->Int32Sub());
896 return Changed(node);
902 Reduction MachineOperatorReducer::ReduceUint32Mod(Node* node) {
903 Uint32BinopMatcher m(node);
904 if (m.left().Is(0))
return Replace(m.left().node());
905 if (m.right().Is(0))
return Replace(m.right().node());
906 if (m.right().Is(1))
return ReplaceUint32(0);
907 if (m.LeftEqualsRight())
return ReplaceInt32(0);
908 if (m.IsFoldable()) {
909 return ReplaceUint32(
910 base::bits::UnsignedMod32(m.left().Value(), m.right().Value()));
912 if (m.right().HasValue()) {
913 Node*
const dividend = m.left().node();
914 uint32_t const divisor = m.right().Value();
915 if (base::bits::IsPowerOfTwo(divisor)) {
916 node->ReplaceInput(1, Uint32Constant(m.right().Value() - 1));
917 node->TrimInputCount(2);
918 NodeProperties::ChangeOp(node, machine()->Word32And());
920 Node* quotient = Uint32Div(dividend, divisor);
921 DCHECK_EQ(dividend, node->InputAt(0));
922 node->ReplaceInput(1, Int32Mul(quotient, Uint32Constant(divisor)));
923 node->TrimInputCount(2);
924 NodeProperties::ChangeOp(node, machine()->Int32Sub());
926 return Changed(node);
932 Reduction MachineOperatorReducer::ReduceStore(Node* node) {
933 NodeMatcher nm(node);
934 MachineRepresentation rep;
937 rep = StoreRepresentationOf(node->op()).representation();
940 DCHECK(nm.IsUnalignedStore());
941 rep = UnalignedStoreRepresentationOf(node->op());
945 Node*
const value = node->InputAt(value_input);
947 switch (value->opcode()) {
948 case IrOpcode::kWord32And: {
949 Uint32BinopMatcher m(value);
950 if (m.right().HasValue() && ((rep == MachineRepresentation::kWord8 &&
951 (m.right().Value() & 0xFF) == 0xFF) ||
952 (rep == MachineRepresentation::kWord16 &&
953 (m.right().Value() & 0xFFFF) == 0xFFFF))) {
954 node->ReplaceInput(value_input, m.left().node());
955 return Changed(node);
959 case IrOpcode::kWord32Sar: {
960 Int32BinopMatcher m(value);
961 if (m.left().IsWord32Shl() && ((rep == MachineRepresentation::kWord8 &&
962 m.right().IsInRange(1, 24)) ||
963 (rep == MachineRepresentation::kWord16 &&
964 m.right().IsInRange(1, 16)))) {
965 Int32BinopMatcher mleft(m.left().node());
966 if (mleft.right().Is(m.right().Value())) {
967 node->ReplaceInput(value_input, mleft.left().node());
968 return Changed(node);
980 Reduction MachineOperatorReducer::ReduceProjection(
size_t index, Node* node) {
981 switch (node->opcode()) {
982 case IrOpcode::kInt32AddWithOverflow: {
983 DCHECK(index == 0 || index == 1);
984 Int32BinopMatcher m(node);
985 if (m.IsFoldable()) {
987 bool ovf = base::bits::SignedAddOverflow32(m.left().Value(),
988 m.right().Value(), &val);
989 return ReplaceInt32(index == 0 ? val : ovf);
991 if (m.right().Is(0)) {
992 return Replace(index == 0 ? m.left().node() : m.right().node());
996 case IrOpcode::kInt32SubWithOverflow: {
997 DCHECK(index == 0 || index == 1);
998 Int32BinopMatcher m(node);
999 if (m.IsFoldable()) {
1001 bool ovf = base::bits::SignedSubOverflow32(m.left().Value(),
1002 m.right().Value(), &val);
1003 return ReplaceInt32(index == 0 ? val : ovf);
1005 if (m.right().Is(0)) {
1006 return Replace(index == 0 ? m.left().node() : m.right().node());
1010 case IrOpcode::kInt32MulWithOverflow: {
1011 DCHECK(index == 0 || index == 1);
1012 Int32BinopMatcher m(node);
1013 if (m.IsFoldable()) {
1015 bool ovf = base::bits::SignedMulOverflow32(m.left().Value(),
1016 m.right().Value(), &val);
1017 return ReplaceInt32(index == 0 ? val : ovf);
1019 if (m.right().Is(0)) {
1020 return Replace(m.right().node());
1022 if (m.right().Is(1)) {
1023 return index == 0 ? Replace(m.left().node()) : ReplaceInt32(0);
1034 Reduction MachineOperatorReducer::ReduceWord32Shifts(Node* node) {
1035 DCHECK((node->opcode() == IrOpcode::kWord32Shl) ||
1036 (node->opcode() == IrOpcode::kWord32Shr) ||
1037 (node->opcode() == IrOpcode::kWord32Sar));
1038 if (machine()->Word32ShiftIsSafe()) {
1041 Int32BinopMatcher m(node);
1042 if (m.right().IsWord32And()) {
1043 Int32BinopMatcher mright(m.right().node());
1044 if (mright.right().Is(0x1F)) {
1045 node->ReplaceInput(1, mright.left().node());
1046 return Changed(node);
1054 Reduction MachineOperatorReducer::ReduceWord32Shl(Node* node) {
1055 DCHECK_EQ(IrOpcode::kWord32Shl, node->opcode());
1056 Int32BinopMatcher m(node);
1057 if (m.right().Is(0))
return Replace(m.left().node());
1058 if (m.IsFoldable()) {
1059 return ReplaceInt32(m.left().Value() << m.right().Value());
1061 if (m.right().IsInRange(1, 31)) {
1064 if (m.left().IsWord32Sar() || m.left().IsWord32Shr()) {
1065 Int32BinopMatcher mleft(m.left().node());
1066 if (mleft.right().Is(m.right().Value())) {
1067 node->ReplaceInput(0, mleft.left().node());
1068 node->ReplaceInput(1,
1069 Uint32Constant(~((1U << m.right().Value()) - 1U)));
1070 NodeProperties::ChangeOp(node, machine()->Word32And());
1071 Reduction reduction = ReduceWord32And(node);
1072 return reduction.Changed() ? reduction : Changed(node);
1076 return ReduceWord32Shifts(node);
1079 Reduction MachineOperatorReducer::ReduceWord64Shl(Node* node) {
1080 DCHECK_EQ(IrOpcode::kWord64Shl, node->opcode());
1081 Int64BinopMatcher m(node);
1082 if (m.right().Is(0))
return Replace(m.left().node());
1083 if (m.IsFoldable()) {
1084 return ReplaceInt64(m.left().Value() << m.right().Value());
1089 Reduction MachineOperatorReducer::ReduceWord32Shr(Node* node) {
1090 Uint32BinopMatcher m(node);
1091 if (m.right().Is(0))
return Replace(m.left().node());
1092 if (m.IsFoldable()) {
1093 return ReplaceInt32(m.left().Value() >> m.right().Value());
1095 if (m.left().IsWord32And() && m.right().HasValue()) {
1096 Uint32BinopMatcher mleft(m.left().node());
1097 if (mleft.right().HasValue()) {
1098 uint32_t shift = m.right().Value() & 0x1F;
1099 uint32_t mask = mleft.right().Value();
1100 if ((mask >> shift) == 0) {
1102 return ReplaceInt32(0);
1106 return ReduceWord32Shifts(node);
1109 Reduction MachineOperatorReducer::ReduceWord64Shr(Node* node) {
1110 DCHECK_EQ(IrOpcode::kWord64Shr, node->opcode());
1111 Uint64BinopMatcher m(node);
1112 if (m.right().Is(0))
return Replace(m.left().node());
1113 if (m.IsFoldable()) {
1114 return ReplaceInt64(m.left().Value() >> m.right().Value());
1119 Reduction MachineOperatorReducer::ReduceWord32Sar(Node* node) {
1120 Int32BinopMatcher m(node);
1121 if (m.right().Is(0))
return Replace(m.left().node());
1122 if (m.IsFoldable()) {
1123 return ReplaceInt32(m.left().Value() >> m.right().Value());
1125 if (m.left().IsWord32Shl()) {
1126 Int32BinopMatcher mleft(m.left().node());
1127 if (mleft.left().IsComparison()) {
1128 if (m.right().Is(31) && mleft.right().Is(31)) {
1130 node->ReplaceInput(0, Int32Constant(0));
1131 node->ReplaceInput(1, mleft.left().node());
1132 NodeProperties::ChangeOp(node, machine()->Int32Sub());
1133 Reduction
const reduction = ReduceInt32Sub(node);
1134 return reduction.Changed() ? reduction : Changed(node);
1136 }
else if (mleft.left().IsLoad()) {
1137 LoadRepresentation
const rep =
1138 LoadRepresentationOf(mleft.left().node()->op());
1139 if (m.right().Is(24) && mleft.right().Is(24) &&
1140 rep == MachineType::Int8()) {
1142 return Replace(mleft.left().node());
1144 if (m.right().Is(16) && mleft.right().Is(16) &&
1145 rep == MachineType::Int16()) {
1147 return Replace(mleft.left().node());
1151 return ReduceWord32Shifts(node);
1154 Reduction MachineOperatorReducer::ReduceWord64Sar(Node* node) {
1155 Int64BinopMatcher m(node);
1156 if (m.right().Is(0))
return Replace(m.left().node());
1157 if (m.IsFoldable()) {
1158 return ReplaceInt64(m.left().Value() >> m.right().Value());
1163 Reduction MachineOperatorReducer::ReduceWord32And(Node* node) {
1164 DCHECK_EQ(IrOpcode::kWord32And, node->opcode());
1165 Int32BinopMatcher m(node);
1166 if (m.right().Is(0))
return Replace(m.right().node());
1167 if (m.right().Is(-1))
return Replace(m.left().node());
1168 if (m.left().IsComparison() && m.right().Is(1)) {
1169 return Replace(m.left().node());
1171 if (m.IsFoldable()) {
1172 return ReplaceInt32(m.left().Value() & m.right().Value());
1174 if (m.LeftEqualsRight())
return Replace(m.left().node());
1175 if (m.left().IsWord32And() && m.right().HasValue()) {
1176 Int32BinopMatcher mleft(m.left().node());
1177 if (mleft.right().HasValue()) {
1178 node->ReplaceInput(0, mleft.left().node());
1180 1, Int32Constant(m.right().Value() & mleft.right().Value()));
1181 Reduction
const reduction = ReduceWord32And(node);
1182 return reduction.Changed() ? reduction : Changed(node);
1185 if (m.right().IsNegativePowerOf2()) {
1186 int32_t
const mask = m.right().Value();
1187 if (m.left().IsWord32Shl()) {
1188 Uint32BinopMatcher mleft(m.left().node());
1189 if (mleft.right().HasValue() &&
1190 (mleft.right().Value() & 0x1F) >=
1191 base::bits::CountTrailingZeros(mask)) {
1193 return Replace(mleft.node());
1195 }
else if (m.left().IsInt32Add()) {
1196 Int32BinopMatcher mleft(m.left().node());
1197 if (mleft.right().HasValue() &&
1198 (mleft.right().Value() & mask) == mleft.right().Value()) {
1200 node->ReplaceInput(0, Word32And(mleft.left().node(), m.right().node()));
1201 node->ReplaceInput(1, mleft.right().node());
1202 NodeProperties::ChangeOp(node, machine()->Int32Add());
1203 Reduction
const reduction = ReduceInt32Add(node);
1204 return reduction.Changed() ? reduction : Changed(node);
1206 if (mleft.left().IsInt32Mul()) {
1207 Int32BinopMatcher mleftleft(mleft.left().node());
1208 if (mleftleft.right().IsMultipleOf(-mask)) {
1210 node->ReplaceInput(0,
1211 Word32And(mleft.right().node(), m.right().node()));
1212 node->ReplaceInput(1, mleftleft.node());
1213 NodeProperties::ChangeOp(node, machine()->Int32Add());
1214 Reduction
const reduction = ReduceInt32Add(node);
1215 return reduction.Changed() ? reduction : Changed(node);
1218 if (mleft.right().IsInt32Mul()) {
1219 Int32BinopMatcher mleftright(mleft.right().node());
1220 if (mleftright.right().IsMultipleOf(-mask)) {
1222 node->ReplaceInput(0,
1223 Word32And(mleft.left().node(), m.right().node()));
1224 node->ReplaceInput(1, mleftright.node());
1225 NodeProperties::ChangeOp(node, machine()->Int32Add());
1226 Reduction
const reduction = ReduceInt32Add(node);
1227 return reduction.Changed() ? reduction : Changed(node);
1230 if (mleft.left().IsWord32Shl()) {
1231 Int32BinopMatcher mleftleft(mleft.left().node());
1232 if (mleftleft.right().Is(base::bits::CountTrailingZeros(mask))) {
1234 node->ReplaceInput(0,
1235 Word32And(mleft.right().node(), m.right().node()));
1236 node->ReplaceInput(1, mleftleft.node());
1237 NodeProperties::ChangeOp(node, machine()->Int32Add());
1238 Reduction
const reduction = ReduceInt32Add(node);
1239 return reduction.Changed() ? reduction : Changed(node);
1242 if (mleft.right().IsWord32Shl()) {
1243 Int32BinopMatcher mleftright(mleft.right().node());
1244 if (mleftright.right().Is(base::bits::CountTrailingZeros(mask))) {
1246 node->ReplaceInput(0,
1247 Word32And(mleft.left().node(), m.right().node()));
1248 node->ReplaceInput(1, mleftright.node());
1249 NodeProperties::ChangeOp(node, machine()->Int32Add());
1250 Reduction
const reduction = ReduceInt32Add(node);
1251 return reduction.Changed() ? reduction : Changed(node);
1254 }
else if (m.left().IsInt32Mul()) {
1255 Int32BinopMatcher mleft(m.left().node());
1256 if (mleft.right().IsMultipleOf(-mask)) {
1258 return Replace(mleft.node());
1265 Reduction MachineOperatorReducer::TryMatchWord32Ror(Node* node) {
1266 DCHECK(IrOpcode::kWord32Or == node->opcode() ||
1267 IrOpcode::kWord32Xor == node->opcode());
1268 Int32BinopMatcher m(node);
1269 Node* shl =
nullptr;
1270 Node* shr =
nullptr;
1277 if (m.left().IsWord32Shl() && m.right().IsWord32Shr()) {
1278 shl = m.left().node();
1279 shr = m.right().node();
1280 }
else if (m.left().IsWord32Shr() && m.right().IsWord32Shl()) {
1281 shl = m.right().node();
1282 shr = m.left().node();
1287 Int32BinopMatcher mshl(shl);
1288 Int32BinopMatcher mshr(shr);
1289 if (mshl.left().node() != mshr.left().node())
return NoChange();
1291 if (mshl.right().HasValue() && mshr.right().HasValue()) {
1293 if (mshl.right().Value() + mshr.right().Value() != 32)
return NoChange();
1295 Node* sub =
nullptr;
1297 if (mshl.right().IsInt32Sub()) {
1298 sub = mshl.right().node();
1299 y = mshr.right().node();
1300 }
else if (mshr.right().IsInt32Sub()) {
1301 sub = mshr.right().node();
1302 y = mshl.right().node();
1307 Int32BinopMatcher msub(sub);
1308 if (!msub.left().Is(32) || msub.right().node() != y)
return NoChange();
1311 node->ReplaceInput(0, mshl.left().node());
1312 node->ReplaceInput(1, mshr.right().node());
1313 NodeProperties::ChangeOp(node, machine()->Word32Ror());
1314 return Changed(node);
1317 Reduction MachineOperatorReducer::ReduceWord32Or(Node* node) {
1318 DCHECK_EQ(IrOpcode::kWord32Or, node->opcode());
1319 Int32BinopMatcher m(node);
1320 if (m.right().Is(0))
return Replace(m.left().node());
1321 if (m.right().Is(-1))
return Replace(m.right().node());
1322 if (m.IsFoldable()) {
1323 return ReplaceInt32(m.left().Value() | m.right().Value());
1325 if (m.LeftEqualsRight())
return Replace(m.left().node());
1327 return TryMatchWord32Ror(node);
1330 Reduction MachineOperatorReducer::ReduceWord32Xor(Node* node) {
1331 DCHECK_EQ(IrOpcode::kWord32Xor, node->opcode());
1332 Int32BinopMatcher m(node);
1333 if (m.right().Is(0))
return Replace(m.left().node());
1334 if (m.IsFoldable()) {
1335 return ReplaceInt32(m.left().Value() ^ m.right().Value());
1337 if (m.LeftEqualsRight())
return ReplaceInt32(0);
1338 if (m.left().IsWord32Xor() && m.right().Is(-1)) {
1339 Int32BinopMatcher mleft(m.left().node());
1340 if (mleft.right().Is(-1)) {
1341 return Replace(mleft.left().node());
1345 return TryMatchWord32Ror(node);
1348 Reduction MachineOperatorReducer::ReduceFloat64InsertLowWord32(Node* node) {
1349 DCHECK_EQ(IrOpcode::kFloat64InsertLowWord32, node->opcode());
1350 Float64Matcher mlhs(node->InputAt(0));
1351 Uint32Matcher mrhs(node->InputAt(1));
1352 if (mlhs.HasValue() && mrhs.HasValue()) {
1353 return ReplaceFloat64(bit_cast<double>(
1354 (bit_cast<uint64_t>(mlhs.Value()) & uint64_t{0xFFFFFFFF00000000}) |
1361 Reduction MachineOperatorReducer::ReduceFloat64InsertHighWord32(Node* node) {
1362 DCHECK_EQ(IrOpcode::kFloat64InsertHighWord32, node->opcode());
1363 Float64Matcher mlhs(node->InputAt(0));
1364 Uint32Matcher mrhs(node->InputAt(1));
1365 if (mlhs.HasValue() && mrhs.HasValue()) {
1366 return ReplaceFloat64(bit_cast<double>(
1367 (bit_cast<uint64_t>(mlhs.Value()) & uint64_t{0xFFFFFFFF}) |
1368 (static_cast<uint64_t>(mrhs.Value()) << 32)));
1376 bool IsFloat64RepresentableAsFloat32(
const Float64Matcher& m) {
1378 double v = m.Value();
1379 float fv =
static_cast<float>(v);
1380 return static_cast<double>(fv) == v;
1388 Reduction MachineOperatorReducer::ReduceFloat64Compare(Node* node) {
1389 DCHECK(IrOpcode::kFloat64Equal == node->opcode() ||
1390 IrOpcode::kFloat64LessThan == node->opcode() ||
1391 IrOpcode::kFloat64LessThanOrEqual == node->opcode());
1392 Float64BinopMatcher m(node);
1393 if (m.IsFoldable()) {
1394 switch (node->opcode()) {
1395 case IrOpcode::kFloat64Equal:
1396 return ReplaceBool(m.left().Value() == m.right().Value());
1397 case IrOpcode::kFloat64LessThan:
1398 return ReplaceBool(m.left().Value() < m.right().Value());
1399 case IrOpcode::kFloat64LessThanOrEqual:
1400 return ReplaceBool(m.left().Value() <= m.right().Value());
1404 }
else if ((m.left().IsChangeFloat32ToFloat64() &&
1405 m.right().IsChangeFloat32ToFloat64()) ||
1406 (m.left().IsChangeFloat32ToFloat64() &&
1407 IsFloat64RepresentableAsFloat32(m.right())) ||
1408 (IsFloat64RepresentableAsFloat32(m.left()) &&
1409 m.right().IsChangeFloat32ToFloat64())) {
1415 switch (node->opcode()) {
1416 case IrOpcode::kFloat64Equal:
1417 NodeProperties::ChangeOp(node, machine()->Float32Equal());
1419 case IrOpcode::kFloat64LessThan:
1420 NodeProperties::ChangeOp(node, machine()->Float32LessThan());
1422 case IrOpcode::kFloat64LessThanOrEqual:
1423 NodeProperties::ChangeOp(node, machine()->Float32LessThanOrEqual());
1429 0, m.left().HasValue()
1430 ? Float32Constant(static_cast<float>(m.left().Value()))
1431 : m.left().InputAt(0));
1433 1, m.right().HasValue()
1434 ? Float32Constant(static_cast<float>(m.right().Value()))
1435 : m.right().InputAt(0));
1436 return Changed(node);
1441 Reduction MachineOperatorReducer::ReduceFloat64RoundDown(Node* node) {
1442 DCHECK_EQ(IrOpcode::kFloat64RoundDown, node->opcode());
1443 Float64Matcher m(node->InputAt(0));
1445 return ReplaceFloat64(Floor(m.Value()));
1450 CommonOperatorBuilder* MachineOperatorReducer::common()
const {
1451 return mcgraph()->common();
1455 MachineOperatorBuilder* MachineOperatorReducer::machine()
const {
1456 return mcgraph()->machine();
1459 Graph* MachineOperatorReducer::graph()
const {
return mcgraph()->graph(); }