11cb0ef41Sopenharmony_ci// Copyright 2014 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci#include "src/compiler/machine-operator-reducer.h"
61cb0ef41Sopenharmony_ci
71cb0ef41Sopenharmony_ci#include <cmath>
81cb0ef41Sopenharmony_ci#include <limits>
91cb0ef41Sopenharmony_ci
101cb0ef41Sopenharmony_ci#include "src/base/bits.h"
111cb0ef41Sopenharmony_ci#include "src/base/division-by-constant.h"
121cb0ef41Sopenharmony_ci#include "src/base/ieee754.h"
131cb0ef41Sopenharmony_ci#include "src/base/logging.h"
141cb0ef41Sopenharmony_ci#include "src/base/overflowing-math.h"
151cb0ef41Sopenharmony_ci#include "src/codegen/tnode.h"
161cb0ef41Sopenharmony_ci#include "src/compiler/diamond.h"
171cb0ef41Sopenharmony_ci#include "src/compiler/graph.h"
181cb0ef41Sopenharmony_ci#include "src/compiler/js-operator.h"
191cb0ef41Sopenharmony_ci#include "src/compiler/machine-graph.h"
201cb0ef41Sopenharmony_ci#include "src/compiler/node-matchers.h"
211cb0ef41Sopenharmony_ci#include "src/compiler/node-properties.h"
221cb0ef41Sopenharmony_ci#include "src/compiler/opcodes.h"
231cb0ef41Sopenharmony_ci#include "src/numbers/conversions-inl.h"
241cb0ef41Sopenharmony_ci
251cb0ef41Sopenharmony_cinamespace v8 {
261cb0ef41Sopenharmony_cinamespace internal {
271cb0ef41Sopenharmony_cinamespace compiler {
281cb0ef41Sopenharmony_ci
291cb0ef41Sopenharmony_ci// Some optimizations performed by the MachineOperatorReducer can be applied
301cb0ef41Sopenharmony_ci// to both Word32 and Word64 operations. Those are implemented in a generic
311cb0ef41Sopenharmony_ci// way to be reused for different word sizes.
321cb0ef41Sopenharmony_ci// This class adapts a generic algorithm to Word32 operations.
331cb0ef41Sopenharmony_ciclass Word32Adapter {
341cb0ef41Sopenharmony_ci public:
351cb0ef41Sopenharmony_ci  using IntNBinopMatcher = Int32BinopMatcher;
361cb0ef41Sopenharmony_ci  using UintNBinopMatcher = Uint32BinopMatcher;
371cb0ef41Sopenharmony_ci  using intN_t = int32_t;
381cb0ef41Sopenharmony_ci  // WORD_SIZE refers to the N for which this adapter specializes.
391cb0ef41Sopenharmony_ci  static constexpr std::size_t WORD_SIZE = 32;
401cb0ef41Sopenharmony_ci
411cb0ef41Sopenharmony_ci  explicit Word32Adapter(MachineOperatorReducer* reducer) : r_(reducer) {}
421cb0ef41Sopenharmony_ci
431cb0ef41Sopenharmony_ci  template <typename T>
441cb0ef41Sopenharmony_ci  static bool IsWordNAnd(const T& x) {
451cb0ef41Sopenharmony_ci    return x.IsWord32And();
461cb0ef41Sopenharmony_ci  }
471cb0ef41Sopenharmony_ci  template <typename T>
481cb0ef41Sopenharmony_ci  static bool IsWordNShl(const T& x) {
491cb0ef41Sopenharmony_ci    return x.IsWord32Shl();
501cb0ef41Sopenharmony_ci  }
511cb0ef41Sopenharmony_ci  template <typename T>
521cb0ef41Sopenharmony_ci  static bool IsWordNShr(const T& x) {
531cb0ef41Sopenharmony_ci    return x.IsWord32Shr();
541cb0ef41Sopenharmony_ci  }
551cb0ef41Sopenharmony_ci  template <typename T>
561cb0ef41Sopenharmony_ci  static bool IsWordNSar(const T& x) {
571cb0ef41Sopenharmony_ci    return x.IsWord32Sar();
581cb0ef41Sopenharmony_ci  }
591cb0ef41Sopenharmony_ci  template <typename T>
601cb0ef41Sopenharmony_ci  static bool IsWordNXor(const T& x) {
611cb0ef41Sopenharmony_ci    return x.IsWord32Xor();
621cb0ef41Sopenharmony_ci  }
631cb0ef41Sopenharmony_ci  template <typename T>
641cb0ef41Sopenharmony_ci  static bool IsIntNAdd(const T& x) {
651cb0ef41Sopenharmony_ci    return x.IsInt32Add();
661cb0ef41Sopenharmony_ci  }
671cb0ef41Sopenharmony_ci  template <typename T>
681cb0ef41Sopenharmony_ci  static bool IsIntNMul(const T& x) {
691cb0ef41Sopenharmony_ci    return x.IsInt32Mul();
701cb0ef41Sopenharmony_ci  }
711cb0ef41Sopenharmony_ci
721cb0ef41Sopenharmony_ci  const Operator* IntNAdd(MachineOperatorBuilder* machine) {
731cb0ef41Sopenharmony_ci    return machine->Int32Add();
741cb0ef41Sopenharmony_ci  }
751cb0ef41Sopenharmony_ci
761cb0ef41Sopenharmony_ci  Reduction ReplaceIntN(int32_t value) { return r_->ReplaceInt32(value); }
771cb0ef41Sopenharmony_ci  Reduction ReduceWordNAnd(Node* node) { return r_->ReduceWord32And(node); }
781cb0ef41Sopenharmony_ci  Reduction ReduceIntNAdd(Node* node) { return r_->ReduceInt32Add(node); }
791cb0ef41Sopenharmony_ci  Reduction TryMatchWordNRor(Node* node) { return r_->TryMatchWord32Ror(node); }
801cb0ef41Sopenharmony_ci
811cb0ef41Sopenharmony_ci  Node* IntNConstant(int32_t value) { return r_->Int32Constant(value); }
821cb0ef41Sopenharmony_ci  Node* UintNConstant(uint32_t value) { return r_->Uint32Constant(value); }
831cb0ef41Sopenharmony_ci  Node* WordNAnd(Node* lhs, Node* rhs) { return r_->Word32And(lhs, rhs); }
841cb0ef41Sopenharmony_ci
851cb0ef41Sopenharmony_ci private:
861cb0ef41Sopenharmony_ci  MachineOperatorReducer* r_;
871cb0ef41Sopenharmony_ci};
881cb0ef41Sopenharmony_ci
891cb0ef41Sopenharmony_ci// Some optimizations performed by the MachineOperatorReducer can be applied
901cb0ef41Sopenharmony_ci// to both Word32 and Word64 operations. Those are implemented in a generic
911cb0ef41Sopenharmony_ci// way to be reused for different word sizes.
921cb0ef41Sopenharmony_ci// This class adapts a generic algorithm to Word64 operations.
931cb0ef41Sopenharmony_ciclass Word64Adapter {
941cb0ef41Sopenharmony_ci public:
951cb0ef41Sopenharmony_ci  using IntNBinopMatcher = Int64BinopMatcher;
961cb0ef41Sopenharmony_ci  using UintNBinopMatcher = Uint64BinopMatcher;
971cb0ef41Sopenharmony_ci  using intN_t = int64_t;
981cb0ef41Sopenharmony_ci  // WORD_SIZE refers to the N for which this adapter specializes.
991cb0ef41Sopenharmony_ci  static constexpr std::size_t WORD_SIZE = 64;
1001cb0ef41Sopenharmony_ci
1011cb0ef41Sopenharmony_ci  explicit Word64Adapter(MachineOperatorReducer* reducer) : r_(reducer) {}
1021cb0ef41Sopenharmony_ci
1031cb0ef41Sopenharmony_ci  template <typename T>
1041cb0ef41Sopenharmony_ci  static bool IsWordNAnd(const T& x) {
1051cb0ef41Sopenharmony_ci    return x.IsWord64And();
1061cb0ef41Sopenharmony_ci  }
1071cb0ef41Sopenharmony_ci  template <typename T>
1081cb0ef41Sopenharmony_ci  static bool IsWordNShl(const T& x) {
1091cb0ef41Sopenharmony_ci    return x.IsWord64Shl();
1101cb0ef41Sopenharmony_ci  }
1111cb0ef41Sopenharmony_ci  template <typename T>
1121cb0ef41Sopenharmony_ci  static bool IsWordNShr(const T& x) {
1131cb0ef41Sopenharmony_ci    return x.IsWord64Shr();
1141cb0ef41Sopenharmony_ci  }
1151cb0ef41Sopenharmony_ci  template <typename T>
1161cb0ef41Sopenharmony_ci  static bool IsWordNSar(const T& x) {
1171cb0ef41Sopenharmony_ci    return x.IsWord64Sar();
1181cb0ef41Sopenharmony_ci  }
1191cb0ef41Sopenharmony_ci  template <typename T>
1201cb0ef41Sopenharmony_ci  static bool IsWordNXor(const T& x) {
1211cb0ef41Sopenharmony_ci    return x.IsWord64Xor();
1221cb0ef41Sopenharmony_ci  }
1231cb0ef41Sopenharmony_ci  template <typename T>
1241cb0ef41Sopenharmony_ci  static bool IsIntNAdd(const T& x) {
1251cb0ef41Sopenharmony_ci    return x.IsInt64Add();
1261cb0ef41Sopenharmony_ci  }
1271cb0ef41Sopenharmony_ci  template <typename T>
1281cb0ef41Sopenharmony_ci  static bool IsIntNMul(const T& x) {
1291cb0ef41Sopenharmony_ci    return x.IsInt64Mul();
1301cb0ef41Sopenharmony_ci  }
1311cb0ef41Sopenharmony_ci
1321cb0ef41Sopenharmony_ci  static const Operator* IntNAdd(MachineOperatorBuilder* machine) {
1331cb0ef41Sopenharmony_ci    return machine->Int64Add();
1341cb0ef41Sopenharmony_ci  }
1351cb0ef41Sopenharmony_ci
1361cb0ef41Sopenharmony_ci  Reduction ReplaceIntN(int64_t value) { return r_->ReplaceInt64(value); }
1371cb0ef41Sopenharmony_ci  Reduction ReduceWordNAnd(Node* node) { return r_->ReduceWord64And(node); }
1381cb0ef41Sopenharmony_ci  Reduction ReduceIntNAdd(Node* node) { return r_->ReduceInt64Add(node); }
1391cb0ef41Sopenharmony_ci  Reduction TryMatchWordNRor(Node* node) {
1401cb0ef41Sopenharmony_ci    // TODO(nicohartmann@): Add a MachineOperatorReducer::TryMatchWord64Ror.
1411cb0ef41Sopenharmony_ci    return r_->NoChange();
1421cb0ef41Sopenharmony_ci  }
1431cb0ef41Sopenharmony_ci
1441cb0ef41Sopenharmony_ci  Node* IntNConstant(int64_t value) { return r_->Int64Constant(value); }
1451cb0ef41Sopenharmony_ci  Node* UintNConstant(uint64_t value) { return r_->Uint64Constant(value); }
1461cb0ef41Sopenharmony_ci  Node* WordNAnd(Node* lhs, Node* rhs) { return r_->Word64And(lhs, rhs); }
1471cb0ef41Sopenharmony_ci
1481cb0ef41Sopenharmony_ci private:
1491cb0ef41Sopenharmony_ci  MachineOperatorReducer* r_;
1501cb0ef41Sopenharmony_ci};
1511cb0ef41Sopenharmony_ci
1521cb0ef41Sopenharmony_cinamespace {
1531cb0ef41Sopenharmony_ci
1541cb0ef41Sopenharmony_ci// TODO(jgruber): Consider replacing all uses of this function by
1551cb0ef41Sopenharmony_ci// std::numeric_limits<T>::quiet_NaN().
1561cb0ef41Sopenharmony_citemplate <class T>
1571cb0ef41Sopenharmony_ciT SilenceNaN(T x) {
1581cb0ef41Sopenharmony_ci  DCHECK(std::isnan(x));
1591cb0ef41Sopenharmony_ci  // Do some calculation to make a signalling NaN quiet.
1601cb0ef41Sopenharmony_ci  return x - x;
1611cb0ef41Sopenharmony_ci}
1621cb0ef41Sopenharmony_ci
1631cb0ef41Sopenharmony_ci}  // namespace
1641cb0ef41Sopenharmony_ci
1651cb0ef41Sopenharmony_ciMachineOperatorReducer::MachineOperatorReducer(Editor* editor,
1661cb0ef41Sopenharmony_ci                                               MachineGraph* mcgraph,
1671cb0ef41Sopenharmony_ci                                               bool allow_signalling_nan)
1681cb0ef41Sopenharmony_ci    : AdvancedReducer(editor),
1691cb0ef41Sopenharmony_ci      mcgraph_(mcgraph),
1701cb0ef41Sopenharmony_ci      allow_signalling_nan_(allow_signalling_nan) {}
1711cb0ef41Sopenharmony_ci
1721cb0ef41Sopenharmony_ciMachineOperatorReducer::~MachineOperatorReducer() = default;
1731cb0ef41Sopenharmony_ci
1741cb0ef41Sopenharmony_ci
1751cb0ef41Sopenharmony_ciNode* MachineOperatorReducer::Float32Constant(volatile float value) {
1761cb0ef41Sopenharmony_ci  return graph()->NewNode(common()->Float32Constant(value));
1771cb0ef41Sopenharmony_ci}
1781cb0ef41Sopenharmony_ci
1791cb0ef41Sopenharmony_ciNode* MachineOperatorReducer::Float64Constant(volatile double value) {
1801cb0ef41Sopenharmony_ci  return mcgraph()->Float64Constant(value);
1811cb0ef41Sopenharmony_ci}
1821cb0ef41Sopenharmony_ci
1831cb0ef41Sopenharmony_ciNode* MachineOperatorReducer::Int32Constant(int32_t value) {
1841cb0ef41Sopenharmony_ci  return mcgraph()->Int32Constant(value);
1851cb0ef41Sopenharmony_ci}
1861cb0ef41Sopenharmony_ci
1871cb0ef41Sopenharmony_ciNode* MachineOperatorReducer::Int64Constant(int64_t value) {
1881cb0ef41Sopenharmony_ci  return graph()->NewNode(common()->Int64Constant(value));
1891cb0ef41Sopenharmony_ci}
1901cb0ef41Sopenharmony_ci
1911cb0ef41Sopenharmony_ciNode* MachineOperatorReducer::Float64Mul(Node* lhs, Node* rhs) {
1921cb0ef41Sopenharmony_ci  return graph()->NewNode(machine()->Float64Mul(), lhs, rhs);
1931cb0ef41Sopenharmony_ci}
1941cb0ef41Sopenharmony_ci
1951cb0ef41Sopenharmony_ciNode* MachineOperatorReducer::Float64PowHalf(Node* value) {
1961cb0ef41Sopenharmony_ci  value =
1971cb0ef41Sopenharmony_ci      graph()->NewNode(machine()->Float64Add(), Float64Constant(0.0), value);
1981cb0ef41Sopenharmony_ci  Diamond d(graph(), common(),
1991cb0ef41Sopenharmony_ci            graph()->NewNode(machine()->Float64LessThanOrEqual(), value,
2001cb0ef41Sopenharmony_ci                             Float64Constant(-V8_INFINITY)),
2011cb0ef41Sopenharmony_ci            BranchHint::kFalse);
2021cb0ef41Sopenharmony_ci  return d.Phi(MachineRepresentation::kFloat64, Float64Constant(V8_INFINITY),
2031cb0ef41Sopenharmony_ci               graph()->NewNode(machine()->Float64Sqrt(), value));
2041cb0ef41Sopenharmony_ci}
2051cb0ef41Sopenharmony_ci
2061cb0ef41Sopenharmony_ciNode* MachineOperatorReducer::Word32And(Node* lhs, Node* rhs) {
2071cb0ef41Sopenharmony_ci  Node* const node = graph()->NewNode(machine()->Word32And(), lhs, rhs);
2081cb0ef41Sopenharmony_ci  Reduction const reduction = ReduceWord32And(node);
2091cb0ef41Sopenharmony_ci  return reduction.Changed() ? reduction.replacement() : node;
2101cb0ef41Sopenharmony_ci}
2111cb0ef41Sopenharmony_ci
2121cb0ef41Sopenharmony_ciNode* MachineOperatorReducer::Word32Sar(Node* lhs, uint32_t rhs) {
2131cb0ef41Sopenharmony_ci  if (rhs == 0) return lhs;
2141cb0ef41Sopenharmony_ci  return graph()->NewNode(machine()->Word32Sar(), lhs, Uint32Constant(rhs));
2151cb0ef41Sopenharmony_ci}
2161cb0ef41Sopenharmony_ci
2171cb0ef41Sopenharmony_ciNode* MachineOperatorReducer::Word32Shr(Node* lhs, uint32_t rhs) {
2181cb0ef41Sopenharmony_ci  if (rhs == 0) return lhs;
2191cb0ef41Sopenharmony_ci  return graph()->NewNode(machine()->Word32Shr(), lhs, Uint32Constant(rhs));
2201cb0ef41Sopenharmony_ci}
2211cb0ef41Sopenharmony_ci
2221cb0ef41Sopenharmony_ciNode* MachineOperatorReducer::Word32Equal(Node* lhs, Node* rhs) {
2231cb0ef41Sopenharmony_ci  return graph()->NewNode(machine()->Word32Equal(), lhs, rhs);
2241cb0ef41Sopenharmony_ci}
2251cb0ef41Sopenharmony_ci
2261cb0ef41Sopenharmony_ciNode* MachineOperatorReducer::Word64And(Node* lhs, Node* rhs) {
2271cb0ef41Sopenharmony_ci  Node* const node = graph()->NewNode(machine()->Word64And(), lhs, rhs);
2281cb0ef41Sopenharmony_ci  Reduction const reduction = ReduceWord64And(node);
2291cb0ef41Sopenharmony_ci  return reduction.Changed() ? reduction.replacement() : node;
2301cb0ef41Sopenharmony_ci}
2311cb0ef41Sopenharmony_ci
2321cb0ef41Sopenharmony_ciNode* MachineOperatorReducer::Int32Add(Node* lhs, Node* rhs) {
2331cb0ef41Sopenharmony_ci  Node* const node = graph()->NewNode(machine()->Int32Add(), lhs, rhs);
2341cb0ef41Sopenharmony_ci  Reduction const reduction = ReduceInt32Add(node);
2351cb0ef41Sopenharmony_ci  return reduction.Changed() ? reduction.replacement() : node;
2361cb0ef41Sopenharmony_ci}
2371cb0ef41Sopenharmony_ci
2381cb0ef41Sopenharmony_ciNode* MachineOperatorReducer::Int32Sub(Node* lhs, Node* rhs) {
2391cb0ef41Sopenharmony_ci  Node* const node = graph()->NewNode(machine()->Int32Sub(), lhs, rhs);
2401cb0ef41Sopenharmony_ci  Reduction const reduction = ReduceInt32Sub(node);
2411cb0ef41Sopenharmony_ci  return reduction.Changed() ? reduction.replacement() : node;
2421cb0ef41Sopenharmony_ci}
2431cb0ef41Sopenharmony_ci
2441cb0ef41Sopenharmony_ciNode* MachineOperatorReducer::Int32Mul(Node* lhs, Node* rhs) {
2451cb0ef41Sopenharmony_ci  return graph()->NewNode(machine()->Int32Mul(), lhs, rhs);
2461cb0ef41Sopenharmony_ci}
2471cb0ef41Sopenharmony_ci
2481cb0ef41Sopenharmony_ciNode* MachineOperatorReducer::Int32Div(Node* dividend, int32_t divisor) {
2491cb0ef41Sopenharmony_ci  DCHECK_NE(0, divisor);
2501cb0ef41Sopenharmony_ci  DCHECK_NE(std::numeric_limits<int32_t>::min(), divisor);
2511cb0ef41Sopenharmony_ci  base::MagicNumbersForDivision<uint32_t> const mag =
2521cb0ef41Sopenharmony_ci      base::SignedDivisionByConstant(bit_cast<uint32_t>(divisor));
2531cb0ef41Sopenharmony_ci  Node* quotient = graph()->NewNode(machine()->Int32MulHigh(), dividend,
2541cb0ef41Sopenharmony_ci                                    Uint32Constant(mag.multiplier));
2551cb0ef41Sopenharmony_ci  if (divisor > 0 && bit_cast<int32_t>(mag.multiplier) < 0) {
2561cb0ef41Sopenharmony_ci    quotient = Int32Add(quotient, dividend);
2571cb0ef41Sopenharmony_ci  } else if (divisor < 0 && bit_cast<int32_t>(mag.multiplier) > 0) {
2581cb0ef41Sopenharmony_ci    quotient = Int32Sub(quotient, dividend);
2591cb0ef41Sopenharmony_ci  }
2601cb0ef41Sopenharmony_ci  return Int32Add(Word32Sar(quotient, mag.shift), Word32Shr(dividend, 31));
2611cb0ef41Sopenharmony_ci}
2621cb0ef41Sopenharmony_ci
2631cb0ef41Sopenharmony_ciNode* MachineOperatorReducer::Uint32Div(Node* dividend, uint32_t divisor) {
2641cb0ef41Sopenharmony_ci  DCHECK_LT(0u, divisor);
2651cb0ef41Sopenharmony_ci  // If the divisor is even, we can avoid using the expensive fixup by shifting
2661cb0ef41Sopenharmony_ci  // the dividend upfront.
2671cb0ef41Sopenharmony_ci  unsigned const shift = base::bits::CountTrailingZeros(divisor);
2681cb0ef41Sopenharmony_ci  dividend = Word32Shr(dividend, shift);
2691cb0ef41Sopenharmony_ci  divisor >>= shift;
2701cb0ef41Sopenharmony_ci  // Compute the magic number for the (shifted) divisor.
2711cb0ef41Sopenharmony_ci  base::MagicNumbersForDivision<uint32_t> const mag =
2721cb0ef41Sopenharmony_ci      base::UnsignedDivisionByConstant(divisor, shift);
2731cb0ef41Sopenharmony_ci  Node* quotient = graph()->NewNode(machine()->Uint32MulHigh(), dividend,
2741cb0ef41Sopenharmony_ci                                    Uint32Constant(mag.multiplier));
2751cb0ef41Sopenharmony_ci  if (mag.add) {
2761cb0ef41Sopenharmony_ci    DCHECK_LE(1u, mag.shift);
2771cb0ef41Sopenharmony_ci    quotient = Word32Shr(
2781cb0ef41Sopenharmony_ci        Int32Add(Word32Shr(Int32Sub(dividend, quotient), 1), quotient),
2791cb0ef41Sopenharmony_ci        mag.shift - 1);
2801cb0ef41Sopenharmony_ci  } else {
2811cb0ef41Sopenharmony_ci    quotient = Word32Shr(quotient, mag.shift);
2821cb0ef41Sopenharmony_ci  }
2831cb0ef41Sopenharmony_ci  return quotient;
2841cb0ef41Sopenharmony_ci}
2851cb0ef41Sopenharmony_ci
2861cb0ef41Sopenharmony_ciNode* MachineOperatorReducer::TruncateInt64ToInt32(Node* value) {
2871cb0ef41Sopenharmony_ci  Node* const node = graph()->NewNode(machine()->TruncateInt64ToInt32(), value);
2881cb0ef41Sopenharmony_ci  Reduction const reduction = ReduceTruncateInt64ToInt32(node);
2891cb0ef41Sopenharmony_ci  return reduction.Changed() ? reduction.replacement() : node;
2901cb0ef41Sopenharmony_ci}
2911cb0ef41Sopenharmony_ci
2921cb0ef41Sopenharmony_cinamespace {
2931cb0ef41Sopenharmony_cibool ObjectsMayAlias(Node* a, Node* b) {
2941cb0ef41Sopenharmony_ci  if (a != b) {
2951cb0ef41Sopenharmony_ci    if (NodeProperties::IsFreshObject(b)) std::swap(a, b);
2961cb0ef41Sopenharmony_ci    if (NodeProperties::IsFreshObject(a) &&
2971cb0ef41Sopenharmony_ci        (NodeProperties::IsFreshObject(b) ||
2981cb0ef41Sopenharmony_ci         b->opcode() == IrOpcode::kParameter ||
2991cb0ef41Sopenharmony_ci         b->opcode() == IrOpcode::kLoadImmutable ||
3001cb0ef41Sopenharmony_ci         IrOpcode::IsConstantOpcode(b->opcode()))) {
3011cb0ef41Sopenharmony_ci      return false;
3021cb0ef41Sopenharmony_ci    }
3031cb0ef41Sopenharmony_ci  }
3041cb0ef41Sopenharmony_ci  return true;
3051cb0ef41Sopenharmony_ci}
3061cb0ef41Sopenharmony_ci}  // namespace
3071cb0ef41Sopenharmony_ci
3081cb0ef41Sopenharmony_ci// Perform constant folding and strength reduction on machine operators.
3091cb0ef41Sopenharmony_ciReduction MachineOperatorReducer::Reduce(Node* node) {
3101cb0ef41Sopenharmony_ci  switch (node->opcode()) {
3111cb0ef41Sopenharmony_ci    case IrOpcode::kProjection:
3121cb0ef41Sopenharmony_ci      return ReduceProjection(ProjectionIndexOf(node->op()), node->InputAt(0));
3131cb0ef41Sopenharmony_ci    case IrOpcode::kWord32And:
3141cb0ef41Sopenharmony_ci      return ReduceWord32And(node);
3151cb0ef41Sopenharmony_ci    case IrOpcode::kWord64And:
3161cb0ef41Sopenharmony_ci      return ReduceWord64And(node);
3171cb0ef41Sopenharmony_ci    case IrOpcode::kWord32Or:
3181cb0ef41Sopenharmony_ci      return ReduceWord32Or(node);
3191cb0ef41Sopenharmony_ci    case IrOpcode::kWord64Or:
3201cb0ef41Sopenharmony_ci      return ReduceWord64Or(node);
3211cb0ef41Sopenharmony_ci    case IrOpcode::kWord32Xor:
3221cb0ef41Sopenharmony_ci      return ReduceWord32Xor(node);
3231cb0ef41Sopenharmony_ci    case IrOpcode::kWord64Xor:
3241cb0ef41Sopenharmony_ci      return ReduceWord64Xor(node);
3251cb0ef41Sopenharmony_ci    case IrOpcode::kWord32Shl:
3261cb0ef41Sopenharmony_ci      return ReduceWord32Shl(node);
3271cb0ef41Sopenharmony_ci    case IrOpcode::kWord64Shl:
3281cb0ef41Sopenharmony_ci      return ReduceWord64Shl(node);
3291cb0ef41Sopenharmony_ci    case IrOpcode::kWord32Shr:
3301cb0ef41Sopenharmony_ci      return ReduceWord32Shr(node);
3311cb0ef41Sopenharmony_ci    case IrOpcode::kWord64Shr:
3321cb0ef41Sopenharmony_ci      return ReduceWord64Shr(node);
3331cb0ef41Sopenharmony_ci    case IrOpcode::kWord32Sar:
3341cb0ef41Sopenharmony_ci      return ReduceWord32Sar(node);
3351cb0ef41Sopenharmony_ci    case IrOpcode::kWord64Sar:
3361cb0ef41Sopenharmony_ci      return ReduceWord64Sar(node);
3371cb0ef41Sopenharmony_ci    case IrOpcode::kWord32Ror: {
3381cb0ef41Sopenharmony_ci      Int32BinopMatcher m(node);
3391cb0ef41Sopenharmony_ci      if (m.right().Is(0)) return Replace(m.left().node());  // x ror 0 => x
3401cb0ef41Sopenharmony_ci      if (m.IsFoldable()) {  // K ror K => K  (K stands for arbitrary constants)
3411cb0ef41Sopenharmony_ci        return ReplaceInt32(base::bits::RotateRight32(
3421cb0ef41Sopenharmony_ci            m.left().ResolvedValue(), m.right().ResolvedValue() & 31));
3431cb0ef41Sopenharmony_ci      }
3441cb0ef41Sopenharmony_ci      break;
3451cb0ef41Sopenharmony_ci    }
3461cb0ef41Sopenharmony_ci    case IrOpcode::kWord32Equal: {
3471cb0ef41Sopenharmony_ci      return ReduceWord32Equal(node);
3481cb0ef41Sopenharmony_ci    }
3491cb0ef41Sopenharmony_ci    case IrOpcode::kWord64Equal: {
3501cb0ef41Sopenharmony_ci      Int64BinopMatcher m(node);
3511cb0ef41Sopenharmony_ci      if (m.IsFoldable()) {  // K == K => K  (K stands for arbitrary constants)
3521cb0ef41Sopenharmony_ci        return ReplaceBool(m.left().ResolvedValue() ==
3531cb0ef41Sopenharmony_ci                           m.right().ResolvedValue());
3541cb0ef41Sopenharmony_ci      }
3551cb0ef41Sopenharmony_ci      if (m.left().IsInt64Sub() && m.right().Is(0)) {  // x - y == 0 => x == y
3561cb0ef41Sopenharmony_ci        Int64BinopMatcher msub(m.left().node());
3571cb0ef41Sopenharmony_ci        node->ReplaceInput(0, msub.left().node());
3581cb0ef41Sopenharmony_ci        node->ReplaceInput(1, msub.right().node());
3591cb0ef41Sopenharmony_ci        return Changed(node);
3601cb0ef41Sopenharmony_ci      }
3611cb0ef41Sopenharmony_ci      // TODO(turbofan): fold HeapConstant, ExternalReference, pointer compares
3621cb0ef41Sopenharmony_ci      if (m.LeftEqualsRight()) return ReplaceBool(true);  // x == x => true
3631cb0ef41Sopenharmony_ci      // This is a workaround for not having escape analysis for wasm
3641cb0ef41Sopenharmony_ci      // (machine-level) turbofan graphs.
3651cb0ef41Sopenharmony_ci      if (!ObjectsMayAlias(m.left().node(), m.right().node())) {
3661cb0ef41Sopenharmony_ci        return ReplaceBool(false);
3671cb0ef41Sopenharmony_ci      }
3681cb0ef41Sopenharmony_ci      break;
3691cb0ef41Sopenharmony_ci    }
3701cb0ef41Sopenharmony_ci    case IrOpcode::kInt32Add:
3711cb0ef41Sopenharmony_ci      return ReduceInt32Add(node);
3721cb0ef41Sopenharmony_ci    case IrOpcode::kInt64Add:
3731cb0ef41Sopenharmony_ci      return ReduceInt64Add(node);
3741cb0ef41Sopenharmony_ci    case IrOpcode::kInt32Sub:
3751cb0ef41Sopenharmony_ci      return ReduceInt32Sub(node);
3761cb0ef41Sopenharmony_ci    case IrOpcode::kInt64Sub:
3771cb0ef41Sopenharmony_ci      return ReduceInt64Sub(node);
3781cb0ef41Sopenharmony_ci    case IrOpcode::kInt32Mul: {
3791cb0ef41Sopenharmony_ci      Int32BinopMatcher m(node);
3801cb0ef41Sopenharmony_ci      if (m.right().Is(0)) return Replace(m.right().node());  // x * 0 => 0
3811cb0ef41Sopenharmony_ci      if (m.right().Is(1)) return Replace(m.left().node());   // x * 1 => x
3821cb0ef41Sopenharmony_ci      if (m.IsFoldable()) {  // K * K => K  (K stands for arbitrary constants)
3831cb0ef41Sopenharmony_ci        return ReplaceInt32(base::MulWithWraparound(m.left().ResolvedValue(),
3841cb0ef41Sopenharmony_ci                                                    m.right().ResolvedValue()));
3851cb0ef41Sopenharmony_ci      }
3861cb0ef41Sopenharmony_ci      if (m.right().Is(-1)) {  // x * -1 => 0 - x
3871cb0ef41Sopenharmony_ci        node->ReplaceInput(0, Int32Constant(0));
3881cb0ef41Sopenharmony_ci        node->ReplaceInput(1, m.left().node());
3891cb0ef41Sopenharmony_ci        NodeProperties::ChangeOp(node, machine()->Int32Sub());
3901cb0ef41Sopenharmony_ci        return Changed(node);
3911cb0ef41Sopenharmony_ci      }
3921cb0ef41Sopenharmony_ci      if (m.right().IsPowerOf2()) {  // x * 2^n => x << n
3931cb0ef41Sopenharmony_ci        node->ReplaceInput(1, Int32Constant(base::bits::WhichPowerOfTwo(
3941cb0ef41Sopenharmony_ci                                  m.right().ResolvedValue())));
3951cb0ef41Sopenharmony_ci        NodeProperties::ChangeOp(node, machine()->Word32Shl());
3961cb0ef41Sopenharmony_ci        return Changed(node).FollowedBy(ReduceWord32Shl(node));
3971cb0ef41Sopenharmony_ci      }
3981cb0ef41Sopenharmony_ci      // (x * Int32Constant(a)) * Int32Constant(b)) => x * Int32Constant(a * b)
3991cb0ef41Sopenharmony_ci      if (m.right().HasResolvedValue() && m.left().IsInt32Mul()) {
4001cb0ef41Sopenharmony_ci        Int32BinopMatcher n(m.left().node());
4011cb0ef41Sopenharmony_ci        if (n.right().HasResolvedValue() && m.OwnsInput(m.left().node())) {
4021cb0ef41Sopenharmony_ci          node->ReplaceInput(
4031cb0ef41Sopenharmony_ci              1, Int32Constant(base::MulWithWraparound(
4041cb0ef41Sopenharmony_ci                     m.right().ResolvedValue(), n.right().ResolvedValue())));
4051cb0ef41Sopenharmony_ci          node->ReplaceInput(0, n.left().node());
4061cb0ef41Sopenharmony_ci          return Changed(node);
4071cb0ef41Sopenharmony_ci        }
4081cb0ef41Sopenharmony_ci      }
4091cb0ef41Sopenharmony_ci      break;
4101cb0ef41Sopenharmony_ci    }
4111cb0ef41Sopenharmony_ci    case IrOpcode::kInt32MulWithOverflow: {
4121cb0ef41Sopenharmony_ci      Int32BinopMatcher m(node);
4131cb0ef41Sopenharmony_ci      if (m.right().Is(2)) {
4141cb0ef41Sopenharmony_ci        node->ReplaceInput(1, m.left().node());
4151cb0ef41Sopenharmony_ci        NodeProperties::ChangeOp(node, machine()->Int32AddWithOverflow());
4161cb0ef41Sopenharmony_ci        return Changed(node);
4171cb0ef41Sopenharmony_ci      }
4181cb0ef41Sopenharmony_ci      if (m.right().Is(-1)) {
4191cb0ef41Sopenharmony_ci        node->ReplaceInput(0, Int32Constant(0));
4201cb0ef41Sopenharmony_ci        node->ReplaceInput(1, m.left().node());
4211cb0ef41Sopenharmony_ci        NodeProperties::ChangeOp(node, machine()->Int32SubWithOverflow());
4221cb0ef41Sopenharmony_ci        return Changed(node);
4231cb0ef41Sopenharmony_ci      }
4241cb0ef41Sopenharmony_ci      break;
4251cb0ef41Sopenharmony_ci    }
4261cb0ef41Sopenharmony_ci    case IrOpcode::kInt64Mul:
4271cb0ef41Sopenharmony_ci      return ReduceInt64Mul(node);
4281cb0ef41Sopenharmony_ci    case IrOpcode::kInt32Div:
4291cb0ef41Sopenharmony_ci      return ReduceInt32Div(node);
4301cb0ef41Sopenharmony_ci    case IrOpcode::kUint32Div:
4311cb0ef41Sopenharmony_ci      return ReduceUint32Div(node);
4321cb0ef41Sopenharmony_ci    case IrOpcode::kInt32Mod:
4331cb0ef41Sopenharmony_ci      return ReduceInt32Mod(node);
4341cb0ef41Sopenharmony_ci    case IrOpcode::kUint32Mod:
4351cb0ef41Sopenharmony_ci      return ReduceUint32Mod(node);
4361cb0ef41Sopenharmony_ci    case IrOpcode::kInt32LessThan: {
4371cb0ef41Sopenharmony_ci      Int32BinopMatcher m(node);
4381cb0ef41Sopenharmony_ci      if (m.IsFoldable()) {  // K < K => K  (K stands for arbitrary constants)
4391cb0ef41Sopenharmony_ci        return ReplaceBool(m.left().ResolvedValue() <
4401cb0ef41Sopenharmony_ci                           m.right().ResolvedValue());
4411cb0ef41Sopenharmony_ci      }
4421cb0ef41Sopenharmony_ci      if (m.LeftEqualsRight()) return ReplaceBool(false);  // x < x => false
4431cb0ef41Sopenharmony_ci      if (m.left().IsWord32Or() && m.right().Is(0)) {
4441cb0ef41Sopenharmony_ci        // (x | K) < 0 => true or (K | x) < 0 => true iff K < 0
4451cb0ef41Sopenharmony_ci        Int32BinopMatcher mleftmatcher(m.left().node());
4461cb0ef41Sopenharmony_ci        if (mleftmatcher.left().IsNegative() ||
4471cb0ef41Sopenharmony_ci            mleftmatcher.right().IsNegative()) {
4481cb0ef41Sopenharmony_ci          return ReplaceBool(true);
4491cb0ef41Sopenharmony_ci        }
4501cb0ef41Sopenharmony_ci      }
4511cb0ef41Sopenharmony_ci      return ReduceWord32Comparisons(node);
4521cb0ef41Sopenharmony_ci    }
4531cb0ef41Sopenharmony_ci    case IrOpcode::kInt32LessThanOrEqual: {
4541cb0ef41Sopenharmony_ci      Int32BinopMatcher m(node);
4551cb0ef41Sopenharmony_ci      if (m.IsFoldable()) {  // K <= K => K  (K stands for arbitrary constants)
4561cb0ef41Sopenharmony_ci        return ReplaceBool(m.left().ResolvedValue() <=
4571cb0ef41Sopenharmony_ci                           m.right().ResolvedValue());
4581cb0ef41Sopenharmony_ci      }
4591cb0ef41Sopenharmony_ci      if (m.LeftEqualsRight()) return ReplaceBool(true);  // x <= x => true
4601cb0ef41Sopenharmony_ci      return ReduceWord32Comparisons(node);
4611cb0ef41Sopenharmony_ci    }
4621cb0ef41Sopenharmony_ci    case IrOpcode::kUint32LessThan: {
4631cb0ef41Sopenharmony_ci      Uint32BinopMatcher m(node);
4641cb0ef41Sopenharmony_ci      if (m.left().Is(kMaxUInt32)) return ReplaceBool(false);  // M < x => false
4651cb0ef41Sopenharmony_ci      if (m.right().Is(0)) return ReplaceBool(false);          // x < 0 => false
4661cb0ef41Sopenharmony_ci      if (m.IsFoldable()) {  // K < K => K  (K stands for arbitrary constants)
4671cb0ef41Sopenharmony_ci        return ReplaceBool(m.left().ResolvedValue() <
4681cb0ef41Sopenharmony_ci                           m.right().ResolvedValue());
4691cb0ef41Sopenharmony_ci      }
4701cb0ef41Sopenharmony_ci      if (m.LeftEqualsRight()) return ReplaceBool(false);  // x < x => false
4711cb0ef41Sopenharmony_ci      if (m.left().IsWord32Sar() && m.right().HasResolvedValue()) {
4721cb0ef41Sopenharmony_ci        Int32BinopMatcher mleft(m.left().node());
4731cb0ef41Sopenharmony_ci        if (mleft.right().HasResolvedValue()) {
4741cb0ef41Sopenharmony_ci          // (x >> K) < C => x < (C << K)
4751cb0ef41Sopenharmony_ci          // when C < (M >> K)
4761cb0ef41Sopenharmony_ci          const uint32_t c = m.right().ResolvedValue();
4771cb0ef41Sopenharmony_ci          const uint32_t k = mleft.right().ResolvedValue() & 0x1F;
4781cb0ef41Sopenharmony_ci          if (c < static_cast<uint32_t>(kMaxInt >> k)) {
4791cb0ef41Sopenharmony_ci            node->ReplaceInput(0, mleft.left().node());
4801cb0ef41Sopenharmony_ci            node->ReplaceInput(1, Uint32Constant(c << k));
4811cb0ef41Sopenharmony_ci            return Changed(node);
4821cb0ef41Sopenharmony_ci          }
4831cb0ef41Sopenharmony_ci          // TODO(turbofan): else the comparison is always true.
4841cb0ef41Sopenharmony_ci        }
4851cb0ef41Sopenharmony_ci      }
4861cb0ef41Sopenharmony_ci      return ReduceWord32Comparisons(node);
4871cb0ef41Sopenharmony_ci    }
4881cb0ef41Sopenharmony_ci    case IrOpcode::kUint32LessThanOrEqual: {
4891cb0ef41Sopenharmony_ci      Uint32BinopMatcher m(node);
4901cb0ef41Sopenharmony_ci      if (m.left().Is(0)) return ReplaceBool(true);            // 0 <= x => true
4911cb0ef41Sopenharmony_ci      if (m.right().Is(kMaxUInt32)) return ReplaceBool(true);  // x <= M => true
4921cb0ef41Sopenharmony_ci      if (m.IsFoldable()) {  // K <= K => K  (K stands for arbitrary constants)
4931cb0ef41Sopenharmony_ci        return ReplaceBool(m.left().ResolvedValue() <=
4941cb0ef41Sopenharmony_ci                           m.right().ResolvedValue());
4951cb0ef41Sopenharmony_ci      }
4961cb0ef41Sopenharmony_ci      if (m.LeftEqualsRight()) return ReplaceBool(true);  // x <= x => true
4971cb0ef41Sopenharmony_ci      return ReduceWord32Comparisons(node);
4981cb0ef41Sopenharmony_ci    }
4991cb0ef41Sopenharmony_ci    case IrOpcode::kFloat32Sub: {
5001cb0ef41Sopenharmony_ci      Float32BinopMatcher m(node);
5011cb0ef41Sopenharmony_ci      if (allow_signalling_nan_ && m.right().Is(0) &&
5021cb0ef41Sopenharmony_ci          (std::copysign(1.0, m.right().ResolvedValue()) > 0)) {
5031cb0ef41Sopenharmony_ci        return Replace(m.left().node());  // x - 0 => x
5041cb0ef41Sopenharmony_ci      }
5051cb0ef41Sopenharmony_ci      if (m.right().IsNaN()) {  // x - NaN => NaN
5061cb0ef41Sopenharmony_ci        return ReplaceFloat32(SilenceNaN(m.right().ResolvedValue()));
5071cb0ef41Sopenharmony_ci      }
5081cb0ef41Sopenharmony_ci      if (m.left().IsNaN()) {  // NaN - x => NaN
5091cb0ef41Sopenharmony_ci        return ReplaceFloat32(SilenceNaN(m.left().ResolvedValue()));
5101cb0ef41Sopenharmony_ci      }
5111cb0ef41Sopenharmony_ci      if (m.IsFoldable()) {  // L - R => (L - R)
5121cb0ef41Sopenharmony_ci        return ReplaceFloat32(m.left().ResolvedValue() -
5131cb0ef41Sopenharmony_ci                              m.right().ResolvedValue());
5141cb0ef41Sopenharmony_ci      }
5151cb0ef41Sopenharmony_ci      if (allow_signalling_nan_ && m.left().IsMinusZero()) {
5161cb0ef41Sopenharmony_ci        // -0.0 - round_down(-0.0 - R) => round_up(R)
5171cb0ef41Sopenharmony_ci        if (machine()->Float32RoundUp().IsSupported() &&
5181cb0ef41Sopenharmony_ci            m.right().IsFloat32RoundDown()) {
5191cb0ef41Sopenharmony_ci          if (m.right().InputAt(0)->opcode() == IrOpcode::kFloat32Sub) {
5201cb0ef41Sopenharmony_ci            Float32BinopMatcher mright0(m.right().InputAt(0));
5211cb0ef41Sopenharmony_ci            if (mright0.left().IsMinusZero()) {
5221cb0ef41Sopenharmony_ci              return Replace(graph()->NewNode(machine()->Float32RoundUp().op(),
5231cb0ef41Sopenharmony_ci                                              mright0.right().node()));
5241cb0ef41Sopenharmony_ci            }
5251cb0ef41Sopenharmony_ci          }
5261cb0ef41Sopenharmony_ci        }
5271cb0ef41Sopenharmony_ci        // -0.0 - R => -R
5281cb0ef41Sopenharmony_ci        node->RemoveInput(0);
5291cb0ef41Sopenharmony_ci        NodeProperties::ChangeOp(node, machine()->Float32Neg());
5301cb0ef41Sopenharmony_ci        return Changed(node);
5311cb0ef41Sopenharmony_ci      }
5321cb0ef41Sopenharmony_ci      break;
5331cb0ef41Sopenharmony_ci    }
5341cb0ef41Sopenharmony_ci    case IrOpcode::kFloat64Add: {
5351cb0ef41Sopenharmony_ci      Float64BinopMatcher m(node);
5361cb0ef41Sopenharmony_ci      if (m.right().IsNaN()) {  // x + NaN => NaN
5371cb0ef41Sopenharmony_ci        return ReplaceFloat64(SilenceNaN(m.right().ResolvedValue()));
5381cb0ef41Sopenharmony_ci      }
5391cb0ef41Sopenharmony_ci      if (m.left().IsNaN()) {  // NaN + x => NaN
5401cb0ef41Sopenharmony_ci        return ReplaceFloat64(SilenceNaN(m.left().ResolvedValue()));
5411cb0ef41Sopenharmony_ci      }
5421cb0ef41Sopenharmony_ci      if (m.IsFoldable()) {  // K + K => K  (K stands for arbitrary constants)
5431cb0ef41Sopenharmony_ci        return ReplaceFloat64(m.left().ResolvedValue() +
5441cb0ef41Sopenharmony_ci                              m.right().ResolvedValue());
5451cb0ef41Sopenharmony_ci      }
5461cb0ef41Sopenharmony_ci      break;
5471cb0ef41Sopenharmony_ci    }
5481cb0ef41Sopenharmony_ci    case IrOpcode::kFloat64Sub: {
5491cb0ef41Sopenharmony_ci      Float64BinopMatcher m(node);
5501cb0ef41Sopenharmony_ci      if (allow_signalling_nan_ && m.right().Is(0) &&
5511cb0ef41Sopenharmony_ci          (base::Double(m.right().ResolvedValue()).Sign() > 0)) {
5521cb0ef41Sopenharmony_ci        return Replace(m.left().node());  // x - 0 => x
5531cb0ef41Sopenharmony_ci      }
5541cb0ef41Sopenharmony_ci      if (m.right().IsNaN()) {  // x - NaN => NaN
5551cb0ef41Sopenharmony_ci        return ReplaceFloat64(SilenceNaN(m.right().ResolvedValue()));
5561cb0ef41Sopenharmony_ci      }
5571cb0ef41Sopenharmony_ci      if (m.left().IsNaN()) {  // NaN - x => NaN
5581cb0ef41Sopenharmony_ci        return ReplaceFloat64(SilenceNaN(m.left().ResolvedValue()));
5591cb0ef41Sopenharmony_ci      }
5601cb0ef41Sopenharmony_ci      if (m.IsFoldable()) {  // L - R => (L - R)
5611cb0ef41Sopenharmony_ci        return ReplaceFloat64(m.left().ResolvedValue() -
5621cb0ef41Sopenharmony_ci                              m.right().ResolvedValue());
5631cb0ef41Sopenharmony_ci      }
5641cb0ef41Sopenharmony_ci      if (allow_signalling_nan_ && m.left().IsMinusZero()) {
5651cb0ef41Sopenharmony_ci        // -0.0 - round_down(-0.0 - R) => round_up(R)
5661cb0ef41Sopenharmony_ci        if (machine()->Float64RoundUp().IsSupported() &&
5671cb0ef41Sopenharmony_ci            m.right().IsFloat64RoundDown()) {
5681cb0ef41Sopenharmony_ci          if (m.right().InputAt(0)->opcode() == IrOpcode::kFloat64Sub) {
5691cb0ef41Sopenharmony_ci            Float64BinopMatcher mright0(m.right().InputAt(0));
5701cb0ef41Sopenharmony_ci            if (mright0.left().IsMinusZero()) {
5711cb0ef41Sopenharmony_ci              return Replace(graph()->NewNode(machine()->Float64RoundUp().op(),
5721cb0ef41Sopenharmony_ci                                              mright0.right().node()));
5731cb0ef41Sopenharmony_ci            }
5741cb0ef41Sopenharmony_ci          }
5751cb0ef41Sopenharmony_ci        }
5761cb0ef41Sopenharmony_ci        // -0.0 - R => -R
5771cb0ef41Sopenharmony_ci        node->RemoveInput(0);
5781cb0ef41Sopenharmony_ci        NodeProperties::ChangeOp(node, machine()->Float64Neg());
5791cb0ef41Sopenharmony_ci        return Changed(node);
5801cb0ef41Sopenharmony_ci      }
5811cb0ef41Sopenharmony_ci      break;
5821cb0ef41Sopenharmony_ci    }
5831cb0ef41Sopenharmony_ci    case IrOpcode::kFloat64Mul: {
5841cb0ef41Sopenharmony_ci      Float64BinopMatcher m(node);
5851cb0ef41Sopenharmony_ci      if (allow_signalling_nan_ && m.right().Is(1))
5861cb0ef41Sopenharmony_ci        return Replace(m.left().node());  // x * 1.0 => x
5871cb0ef41Sopenharmony_ci      if (m.right().Is(-1)) {  // x * -1.0 => -0.0 - x
5881cb0ef41Sopenharmony_ci        node->ReplaceInput(0, Float64Constant(-0.0));
5891cb0ef41Sopenharmony_ci        node->ReplaceInput(1, m.left().node());
5901cb0ef41Sopenharmony_ci        NodeProperties::ChangeOp(node, machine()->Float64Sub());
5911cb0ef41Sopenharmony_ci        return Changed(node);
5921cb0ef41Sopenharmony_ci      }
5931cb0ef41Sopenharmony_ci      if (m.right().IsNaN()) {                               // x * NaN => NaN
5941cb0ef41Sopenharmony_ci        return ReplaceFloat64(SilenceNaN(m.right().ResolvedValue()));
5951cb0ef41Sopenharmony_ci      }
5961cb0ef41Sopenharmony_ci      if (m.IsFoldable()) {  // K * K => K  (K stands for arbitrary constants)
5971cb0ef41Sopenharmony_ci        return ReplaceFloat64(m.left().ResolvedValue() *
5981cb0ef41Sopenharmony_ci                              m.right().ResolvedValue());
5991cb0ef41Sopenharmony_ci      }
6001cb0ef41Sopenharmony_ci      if (m.right().Is(2)) {  // x * 2.0 => x + x
6011cb0ef41Sopenharmony_ci        node->ReplaceInput(1, m.left().node());
6021cb0ef41Sopenharmony_ci        NodeProperties::ChangeOp(node, machine()->Float64Add());
6031cb0ef41Sopenharmony_ci        return Changed(node);
6041cb0ef41Sopenharmony_ci      }
6051cb0ef41Sopenharmony_ci      break;
6061cb0ef41Sopenharmony_ci    }
6071cb0ef41Sopenharmony_ci    case IrOpcode::kFloat64Div: {
6081cb0ef41Sopenharmony_ci      Float64BinopMatcher m(node);
6091cb0ef41Sopenharmony_ci      if (allow_signalling_nan_ && m.right().Is(1))
6101cb0ef41Sopenharmony_ci        return Replace(m.left().node());  // x / 1.0 => x
6111cb0ef41Sopenharmony_ci      // TODO(ahaas): We could do x / 1.0 = x if we knew that x is not an sNaN.
6121cb0ef41Sopenharmony_ci      if (m.right().IsNaN()) {                               // x / NaN => NaN
6131cb0ef41Sopenharmony_ci        return ReplaceFloat64(SilenceNaN(m.right().ResolvedValue()));
6141cb0ef41Sopenharmony_ci      }
6151cb0ef41Sopenharmony_ci      if (m.left().IsNaN()) {  // NaN / x => NaN
6161cb0ef41Sopenharmony_ci        return ReplaceFloat64(SilenceNaN(m.left().ResolvedValue()));
6171cb0ef41Sopenharmony_ci      }
6181cb0ef41Sopenharmony_ci      if (m.IsFoldable()) {  // K / K => K  (K stands for arbitrary constants)
6191cb0ef41Sopenharmony_ci        return ReplaceFloat64(
6201cb0ef41Sopenharmony_ci            base::Divide(m.left().ResolvedValue(), m.right().ResolvedValue()));
6211cb0ef41Sopenharmony_ci      }
6221cb0ef41Sopenharmony_ci      if (allow_signalling_nan_ && m.right().Is(-1)) {  // x / -1.0 => -x
6231cb0ef41Sopenharmony_ci        node->RemoveInput(1);
6241cb0ef41Sopenharmony_ci        NodeProperties::ChangeOp(node, machine()->Float64Neg());
6251cb0ef41Sopenharmony_ci        return Changed(node);
6261cb0ef41Sopenharmony_ci      }
6271cb0ef41Sopenharmony_ci      if (m.right().IsNormal() && m.right().IsPositiveOrNegativePowerOf2()) {
6281cb0ef41Sopenharmony_ci        // All reciprocals of non-denormal powers of two can be represented
6291cb0ef41Sopenharmony_ci        // exactly, so division by power of two can be reduced to
6301cb0ef41Sopenharmony_ci        // multiplication by reciprocal, with the same result.
6311cb0ef41Sopenharmony_ci        node->ReplaceInput(1, Float64Constant(1.0 / m.right().ResolvedValue()));
6321cb0ef41Sopenharmony_ci        NodeProperties::ChangeOp(node, machine()->Float64Mul());
6331cb0ef41Sopenharmony_ci        return Changed(node);
6341cb0ef41Sopenharmony_ci      }
6351cb0ef41Sopenharmony_ci      break;
6361cb0ef41Sopenharmony_ci    }
6371cb0ef41Sopenharmony_ci    case IrOpcode::kFloat64Mod: {
6381cb0ef41Sopenharmony_ci      Float64BinopMatcher m(node);
6391cb0ef41Sopenharmony_ci      if (m.right().Is(0)) {  // x % 0 => NaN
6401cb0ef41Sopenharmony_ci        return ReplaceFloat64(std::numeric_limits<double>::quiet_NaN());
6411cb0ef41Sopenharmony_ci      }
6421cb0ef41Sopenharmony_ci      if (m.right().IsNaN()) {  // x % NaN => NaN
6431cb0ef41Sopenharmony_ci        return ReplaceFloat64(SilenceNaN(m.right().ResolvedValue()));
6441cb0ef41Sopenharmony_ci      }
6451cb0ef41Sopenharmony_ci      if (m.left().IsNaN()) {  // NaN % x => NaN
6461cb0ef41Sopenharmony_ci        return ReplaceFloat64(SilenceNaN(m.left().ResolvedValue()));
6471cb0ef41Sopenharmony_ci      }
6481cb0ef41Sopenharmony_ci      if (m.IsFoldable()) {  // K % K => K  (K stands for arbitrary constants)
6491cb0ef41Sopenharmony_ci        return ReplaceFloat64(
6501cb0ef41Sopenharmony_ci            Modulo(m.left().ResolvedValue(), m.right().ResolvedValue()));
6511cb0ef41Sopenharmony_ci      }
6521cb0ef41Sopenharmony_ci      break;
6531cb0ef41Sopenharmony_ci    }
6541cb0ef41Sopenharmony_ci    case IrOpcode::kFloat64Acos: {
6551cb0ef41Sopenharmony_ci      Float64Matcher m(node->InputAt(0));
6561cb0ef41Sopenharmony_ci      if (m.HasResolvedValue())
6571cb0ef41Sopenharmony_ci        return ReplaceFloat64(base::ieee754::acos(m.ResolvedValue()));
6581cb0ef41Sopenharmony_ci      break;
6591cb0ef41Sopenharmony_ci    }
6601cb0ef41Sopenharmony_ci    case IrOpcode::kFloat64Acosh: {
6611cb0ef41Sopenharmony_ci      Float64Matcher m(node->InputAt(0));
6621cb0ef41Sopenharmony_ci      if (m.HasResolvedValue())
6631cb0ef41Sopenharmony_ci        return ReplaceFloat64(base::ieee754::acosh(m.ResolvedValue()));
6641cb0ef41Sopenharmony_ci      break;
6651cb0ef41Sopenharmony_ci    }
6661cb0ef41Sopenharmony_ci    case IrOpcode::kFloat64Asin: {
6671cb0ef41Sopenharmony_ci      Float64Matcher m(node->InputAt(0));
6681cb0ef41Sopenharmony_ci      if (m.HasResolvedValue())
6691cb0ef41Sopenharmony_ci        return ReplaceFloat64(base::ieee754::asin(m.ResolvedValue()));
6701cb0ef41Sopenharmony_ci      break;
6711cb0ef41Sopenharmony_ci    }
6721cb0ef41Sopenharmony_ci    case IrOpcode::kFloat64Asinh: {
6731cb0ef41Sopenharmony_ci      Float64Matcher m(node->InputAt(0));
6741cb0ef41Sopenharmony_ci      if (m.HasResolvedValue())
6751cb0ef41Sopenharmony_ci        return ReplaceFloat64(base::ieee754::asinh(m.ResolvedValue()));
6761cb0ef41Sopenharmony_ci      break;
6771cb0ef41Sopenharmony_ci    }
6781cb0ef41Sopenharmony_ci    case IrOpcode::kFloat64Atan: {
6791cb0ef41Sopenharmony_ci      Float64Matcher m(node->InputAt(0));
6801cb0ef41Sopenharmony_ci      if (m.HasResolvedValue())
6811cb0ef41Sopenharmony_ci        return ReplaceFloat64(base::ieee754::atan(m.ResolvedValue()));
6821cb0ef41Sopenharmony_ci      break;
6831cb0ef41Sopenharmony_ci    }
6841cb0ef41Sopenharmony_ci    case IrOpcode::kFloat64Atanh: {
6851cb0ef41Sopenharmony_ci      Float64Matcher m(node->InputAt(0));
6861cb0ef41Sopenharmony_ci      if (m.HasResolvedValue())
6871cb0ef41Sopenharmony_ci        return ReplaceFloat64(base::ieee754::atanh(m.ResolvedValue()));
6881cb0ef41Sopenharmony_ci      break;
6891cb0ef41Sopenharmony_ci    }
6901cb0ef41Sopenharmony_ci    case IrOpcode::kFloat64Atan2: {
6911cb0ef41Sopenharmony_ci      Float64BinopMatcher m(node);
6921cb0ef41Sopenharmony_ci      if (m.right().IsNaN()) {
6931cb0ef41Sopenharmony_ci        return ReplaceFloat64(SilenceNaN(m.right().ResolvedValue()));
6941cb0ef41Sopenharmony_ci      }
6951cb0ef41Sopenharmony_ci      if (m.left().IsNaN()) {
6961cb0ef41Sopenharmony_ci        return ReplaceFloat64(SilenceNaN(m.left().ResolvedValue()));
6971cb0ef41Sopenharmony_ci      }
6981cb0ef41Sopenharmony_ci      if (m.IsFoldable()) {
6991cb0ef41Sopenharmony_ci        return ReplaceFloat64(base::ieee754::atan2(m.left().ResolvedValue(),
7001cb0ef41Sopenharmony_ci                                                   m.right().ResolvedValue()));
7011cb0ef41Sopenharmony_ci      }
7021cb0ef41Sopenharmony_ci      break;
7031cb0ef41Sopenharmony_ci    }
7041cb0ef41Sopenharmony_ci    case IrOpcode::kFloat64Cbrt: {
7051cb0ef41Sopenharmony_ci      Float64Matcher m(node->InputAt(0));
7061cb0ef41Sopenharmony_ci      if (m.HasResolvedValue())
7071cb0ef41Sopenharmony_ci        return ReplaceFloat64(base::ieee754::cbrt(m.ResolvedValue()));
7081cb0ef41Sopenharmony_ci      break;
7091cb0ef41Sopenharmony_ci    }
7101cb0ef41Sopenharmony_ci    case IrOpcode::kFloat64Cos: {
7111cb0ef41Sopenharmony_ci      Float64Matcher m(node->InputAt(0));
7121cb0ef41Sopenharmony_ci      if (m.HasResolvedValue())
7131cb0ef41Sopenharmony_ci        return ReplaceFloat64(base::ieee754::cos(m.ResolvedValue()));
7141cb0ef41Sopenharmony_ci      break;
7151cb0ef41Sopenharmony_ci    }
7161cb0ef41Sopenharmony_ci    case IrOpcode::kFloat64Cosh: {
7171cb0ef41Sopenharmony_ci      Float64Matcher m(node->InputAt(0));
7181cb0ef41Sopenharmony_ci      if (m.HasResolvedValue())
7191cb0ef41Sopenharmony_ci        return ReplaceFloat64(base::ieee754::cosh(m.ResolvedValue()));
7201cb0ef41Sopenharmony_ci      break;
7211cb0ef41Sopenharmony_ci    }
7221cb0ef41Sopenharmony_ci    case IrOpcode::kFloat64Exp: {
7231cb0ef41Sopenharmony_ci      Float64Matcher m(node->InputAt(0));
7241cb0ef41Sopenharmony_ci      if (m.HasResolvedValue())
7251cb0ef41Sopenharmony_ci        return ReplaceFloat64(base::ieee754::exp(m.ResolvedValue()));
7261cb0ef41Sopenharmony_ci      break;
7271cb0ef41Sopenharmony_ci    }
7281cb0ef41Sopenharmony_ci    case IrOpcode::kFloat64Expm1: {
7291cb0ef41Sopenharmony_ci      Float64Matcher m(node->InputAt(0));
7301cb0ef41Sopenharmony_ci      if (m.HasResolvedValue())
7311cb0ef41Sopenharmony_ci        return ReplaceFloat64(base::ieee754::expm1(m.ResolvedValue()));
7321cb0ef41Sopenharmony_ci      break;
7331cb0ef41Sopenharmony_ci    }
7341cb0ef41Sopenharmony_ci    case IrOpcode::kFloat64Log: {
7351cb0ef41Sopenharmony_ci      Float64Matcher m(node->InputAt(0));
7361cb0ef41Sopenharmony_ci      if (m.HasResolvedValue())
7371cb0ef41Sopenharmony_ci        return ReplaceFloat64(base::ieee754::log(m.ResolvedValue()));
7381cb0ef41Sopenharmony_ci      break;
7391cb0ef41Sopenharmony_ci    }
7401cb0ef41Sopenharmony_ci    case IrOpcode::kFloat64Log1p: {
7411cb0ef41Sopenharmony_ci      Float64Matcher m(node->InputAt(0));
7421cb0ef41Sopenharmony_ci      if (m.HasResolvedValue())
7431cb0ef41Sopenharmony_ci        return ReplaceFloat64(base::ieee754::log1p(m.ResolvedValue()));
7441cb0ef41Sopenharmony_ci      break;
7451cb0ef41Sopenharmony_ci    }
7461cb0ef41Sopenharmony_ci    case IrOpcode::kFloat64Log10: {
7471cb0ef41Sopenharmony_ci      Float64Matcher m(node->InputAt(0));
7481cb0ef41Sopenharmony_ci      if (m.HasResolvedValue())
7491cb0ef41Sopenharmony_ci        return ReplaceFloat64(base::ieee754::log10(m.ResolvedValue()));
7501cb0ef41Sopenharmony_ci      break;
7511cb0ef41Sopenharmony_ci    }
7521cb0ef41Sopenharmony_ci    case IrOpcode::kFloat64Log2: {
7531cb0ef41Sopenharmony_ci      Float64Matcher m(node->InputAt(0));
7541cb0ef41Sopenharmony_ci      if (m.HasResolvedValue())
7551cb0ef41Sopenharmony_ci        return ReplaceFloat64(base::ieee754::log2(m.ResolvedValue()));
7561cb0ef41Sopenharmony_ci      break;
7571cb0ef41Sopenharmony_ci    }
7581cb0ef41Sopenharmony_ci    case IrOpcode::kFloat64Pow: {
7591cb0ef41Sopenharmony_ci      Float64BinopMatcher m(node);
7601cb0ef41Sopenharmony_ci      if (m.IsFoldable()) {
7611cb0ef41Sopenharmony_ci        return ReplaceFloat64(base::ieee754::pow(m.left().ResolvedValue(),
7621cb0ef41Sopenharmony_ci                                                 m.right().ResolvedValue()));
7631cb0ef41Sopenharmony_ci      } else if (m.right().Is(0.0)) {  // x ** +-0.0 => 1.0
7641cb0ef41Sopenharmony_ci        return ReplaceFloat64(1.0);
7651cb0ef41Sopenharmony_ci      } else if (m.right().Is(2.0)) {  // x ** 2.0 => x * x
7661cb0ef41Sopenharmony_ci        node->ReplaceInput(1, m.left().node());
7671cb0ef41Sopenharmony_ci        NodeProperties::ChangeOp(node, machine()->Float64Mul());
7681cb0ef41Sopenharmony_ci        return Changed(node);
7691cb0ef41Sopenharmony_ci      } else if (m.right().Is(0.5)) {
7701cb0ef41Sopenharmony_ci        // x ** 0.5 => if x <= -Infinity then Infinity else sqrt(0.0 + x)
7711cb0ef41Sopenharmony_ci        return Replace(Float64PowHalf(m.left().node()));
7721cb0ef41Sopenharmony_ci      }
7731cb0ef41Sopenharmony_ci      break;
7741cb0ef41Sopenharmony_ci    }
7751cb0ef41Sopenharmony_ci    case IrOpcode::kFloat64Sin: {
7761cb0ef41Sopenharmony_ci      Float64Matcher m(node->InputAt(0));
7771cb0ef41Sopenharmony_ci      if (m.HasResolvedValue())
7781cb0ef41Sopenharmony_ci        return ReplaceFloat64(base::ieee754::sin(m.ResolvedValue()));
7791cb0ef41Sopenharmony_ci      break;
7801cb0ef41Sopenharmony_ci    }
7811cb0ef41Sopenharmony_ci    case IrOpcode::kFloat64Sinh: {
7821cb0ef41Sopenharmony_ci      Float64Matcher m(node->InputAt(0));
7831cb0ef41Sopenharmony_ci      if (m.HasResolvedValue())
7841cb0ef41Sopenharmony_ci        return ReplaceFloat64(base::ieee754::sinh(m.ResolvedValue()));
7851cb0ef41Sopenharmony_ci      break;
7861cb0ef41Sopenharmony_ci    }
7871cb0ef41Sopenharmony_ci    case IrOpcode::kFloat64Tan: {
7881cb0ef41Sopenharmony_ci      Float64Matcher m(node->InputAt(0));
7891cb0ef41Sopenharmony_ci      if (m.HasResolvedValue())
7901cb0ef41Sopenharmony_ci        return ReplaceFloat64(base::ieee754::tan(m.ResolvedValue()));
7911cb0ef41Sopenharmony_ci      break;
7921cb0ef41Sopenharmony_ci    }
7931cb0ef41Sopenharmony_ci    case IrOpcode::kFloat64Tanh: {
7941cb0ef41Sopenharmony_ci      Float64Matcher m(node->InputAt(0));
7951cb0ef41Sopenharmony_ci      if (m.HasResolvedValue())
7961cb0ef41Sopenharmony_ci        return ReplaceFloat64(base::ieee754::tanh(m.ResolvedValue()));
7971cb0ef41Sopenharmony_ci      break;
7981cb0ef41Sopenharmony_ci    }
7991cb0ef41Sopenharmony_ci    case IrOpcode::kChangeFloat32ToFloat64: {
8001cb0ef41Sopenharmony_ci      Float32Matcher m(node->InputAt(0));
8011cb0ef41Sopenharmony_ci      if (m.HasResolvedValue()) {
8021cb0ef41Sopenharmony_ci        if (!allow_signalling_nan_ && std::isnan(m.ResolvedValue())) {
8031cb0ef41Sopenharmony_ci          return ReplaceFloat64(SilenceNaN(m.ResolvedValue()));
8041cb0ef41Sopenharmony_ci        }
8051cb0ef41Sopenharmony_ci        return ReplaceFloat64(m.ResolvedValue());
8061cb0ef41Sopenharmony_ci      }
8071cb0ef41Sopenharmony_ci      break;
8081cb0ef41Sopenharmony_ci    }
8091cb0ef41Sopenharmony_ci    case IrOpcode::kChangeFloat64ToInt32: {
8101cb0ef41Sopenharmony_ci      Float64Matcher m(node->InputAt(0));
8111cb0ef41Sopenharmony_ci      if (m.HasResolvedValue())
8121cb0ef41Sopenharmony_ci        return ReplaceInt32(FastD2IChecked(m.ResolvedValue()));
8131cb0ef41Sopenharmony_ci      if (m.IsChangeInt32ToFloat64()) return Replace(m.node()->InputAt(0));
8141cb0ef41Sopenharmony_ci      break;
8151cb0ef41Sopenharmony_ci    }
8161cb0ef41Sopenharmony_ci    case IrOpcode::kChangeFloat64ToInt64: {
8171cb0ef41Sopenharmony_ci      Float64Matcher m(node->InputAt(0));
8181cb0ef41Sopenharmony_ci      if (m.HasResolvedValue())
8191cb0ef41Sopenharmony_ci        return ReplaceInt64(static_cast<int64_t>(m.ResolvedValue()));
8201cb0ef41Sopenharmony_ci      if (m.IsChangeInt64ToFloat64()) return Replace(m.node()->InputAt(0));
8211cb0ef41Sopenharmony_ci      break;
8221cb0ef41Sopenharmony_ci    }
8231cb0ef41Sopenharmony_ci    case IrOpcode::kChangeFloat64ToUint32: {
8241cb0ef41Sopenharmony_ci      Float64Matcher m(node->InputAt(0));
8251cb0ef41Sopenharmony_ci      if (m.HasResolvedValue())
8261cb0ef41Sopenharmony_ci        return ReplaceInt32(FastD2UI(m.ResolvedValue()));
8271cb0ef41Sopenharmony_ci      if (m.IsChangeUint32ToFloat64()) return Replace(m.node()->InputAt(0));
8281cb0ef41Sopenharmony_ci      break;
8291cb0ef41Sopenharmony_ci    }
8301cb0ef41Sopenharmony_ci    case IrOpcode::kChangeInt32ToFloat64: {
8311cb0ef41Sopenharmony_ci      Int32Matcher m(node->InputAt(0));
8321cb0ef41Sopenharmony_ci      if (m.HasResolvedValue())
8331cb0ef41Sopenharmony_ci        return ReplaceFloat64(FastI2D(m.ResolvedValue()));
8341cb0ef41Sopenharmony_ci      break;
8351cb0ef41Sopenharmony_ci    }
8361cb0ef41Sopenharmony_ci    case IrOpcode::kBitcastWord32ToWord64: {
8371cb0ef41Sopenharmony_ci      Int32Matcher m(node->InputAt(0));
8381cb0ef41Sopenharmony_ci      if (m.HasResolvedValue()) return ReplaceInt64(m.ResolvedValue());
8391cb0ef41Sopenharmony_ci      break;
8401cb0ef41Sopenharmony_ci    }
8411cb0ef41Sopenharmony_ci    case IrOpcode::kChangeInt32ToInt64: {
8421cb0ef41Sopenharmony_ci      Int32Matcher m(node->InputAt(0));
8431cb0ef41Sopenharmony_ci      if (m.HasResolvedValue()) return ReplaceInt64(m.ResolvedValue());
8441cb0ef41Sopenharmony_ci      break;
8451cb0ef41Sopenharmony_ci    }
8461cb0ef41Sopenharmony_ci    case IrOpcode::kChangeInt64ToFloat64: {
8471cb0ef41Sopenharmony_ci      Int64Matcher m(node->InputAt(0));
8481cb0ef41Sopenharmony_ci      if (m.HasResolvedValue())
8491cb0ef41Sopenharmony_ci        return ReplaceFloat64(static_cast<double>(m.ResolvedValue()));
8501cb0ef41Sopenharmony_ci      if (m.IsChangeFloat64ToInt64()) return Replace(m.node()->InputAt(0));
8511cb0ef41Sopenharmony_ci      break;
8521cb0ef41Sopenharmony_ci    }
8531cb0ef41Sopenharmony_ci    case IrOpcode::kChangeUint32ToFloat64: {
8541cb0ef41Sopenharmony_ci      Uint32Matcher m(node->InputAt(0));
8551cb0ef41Sopenharmony_ci      if (m.HasResolvedValue())
8561cb0ef41Sopenharmony_ci        return ReplaceFloat64(FastUI2D(m.ResolvedValue()));
8571cb0ef41Sopenharmony_ci      break;
8581cb0ef41Sopenharmony_ci    }
8591cb0ef41Sopenharmony_ci    case IrOpcode::kChangeUint32ToUint64: {
8601cb0ef41Sopenharmony_ci      Uint32Matcher m(node->InputAt(0));
8611cb0ef41Sopenharmony_ci      if (m.HasResolvedValue())
8621cb0ef41Sopenharmony_ci        return ReplaceInt64(static_cast<uint64_t>(m.ResolvedValue()));
8631cb0ef41Sopenharmony_ci      break;
8641cb0ef41Sopenharmony_ci    }
8651cb0ef41Sopenharmony_ci    case IrOpcode::kTruncateFloat64ToWord32: {
8661cb0ef41Sopenharmony_ci      Float64Matcher m(node->InputAt(0));
8671cb0ef41Sopenharmony_ci      if (m.HasResolvedValue())
8681cb0ef41Sopenharmony_ci        return ReplaceInt32(DoubleToInt32(m.ResolvedValue()));
8691cb0ef41Sopenharmony_ci      if (m.IsChangeInt32ToFloat64()) return Replace(m.node()->InputAt(0));
8701cb0ef41Sopenharmony_ci      return NoChange();
8711cb0ef41Sopenharmony_ci    }
8721cb0ef41Sopenharmony_ci    case IrOpcode::kTruncateInt64ToInt32:
8731cb0ef41Sopenharmony_ci      return ReduceTruncateInt64ToInt32(node);
8741cb0ef41Sopenharmony_ci    case IrOpcode::kTruncateFloat64ToFloat32: {
8751cb0ef41Sopenharmony_ci      Float64Matcher m(node->InputAt(0));
8761cb0ef41Sopenharmony_ci      if (m.HasResolvedValue()) {
8771cb0ef41Sopenharmony_ci        if (!allow_signalling_nan_ && m.IsNaN()) {
8781cb0ef41Sopenharmony_ci          return ReplaceFloat32(DoubleToFloat32(SilenceNaN(m.ResolvedValue())));
8791cb0ef41Sopenharmony_ci        }
8801cb0ef41Sopenharmony_ci        return ReplaceFloat32(DoubleToFloat32(m.ResolvedValue()));
8811cb0ef41Sopenharmony_ci      }
8821cb0ef41Sopenharmony_ci      if (allow_signalling_nan_ && m.IsChangeFloat32ToFloat64())
8831cb0ef41Sopenharmony_ci        return Replace(m.node()->InputAt(0));
8841cb0ef41Sopenharmony_ci      break;
8851cb0ef41Sopenharmony_ci    }
8861cb0ef41Sopenharmony_ci    case IrOpcode::kRoundFloat64ToInt32: {
8871cb0ef41Sopenharmony_ci      Float64Matcher m(node->InputAt(0));
8881cb0ef41Sopenharmony_ci      if (m.HasResolvedValue()) {
8891cb0ef41Sopenharmony_ci        return ReplaceInt32(DoubleToInt32(m.ResolvedValue()));
8901cb0ef41Sopenharmony_ci      }
8911cb0ef41Sopenharmony_ci      if (m.IsChangeInt32ToFloat64()) return Replace(m.node()->InputAt(0));
8921cb0ef41Sopenharmony_ci      break;
8931cb0ef41Sopenharmony_ci    }
8941cb0ef41Sopenharmony_ci    case IrOpcode::kFloat64InsertLowWord32:
8951cb0ef41Sopenharmony_ci      return ReduceFloat64InsertLowWord32(node);
8961cb0ef41Sopenharmony_ci    case IrOpcode::kFloat64InsertHighWord32:
8971cb0ef41Sopenharmony_ci      return ReduceFloat64InsertHighWord32(node);
8981cb0ef41Sopenharmony_ci    case IrOpcode::kStore:
8991cb0ef41Sopenharmony_ci    case IrOpcode::kUnalignedStore:
9001cb0ef41Sopenharmony_ci      return ReduceStore(node);
9011cb0ef41Sopenharmony_ci    case IrOpcode::kFloat64Equal:
9021cb0ef41Sopenharmony_ci    case IrOpcode::kFloat64LessThan:
9031cb0ef41Sopenharmony_ci    case IrOpcode::kFloat64LessThanOrEqual:
9041cb0ef41Sopenharmony_ci      return ReduceFloat64Compare(node);
9051cb0ef41Sopenharmony_ci    case IrOpcode::kFloat64RoundDown:
9061cb0ef41Sopenharmony_ci      return ReduceFloat64RoundDown(node);
9071cb0ef41Sopenharmony_ci    case IrOpcode::kBitcastTaggedToWord:
9081cb0ef41Sopenharmony_ci    case IrOpcode::kBitcastTaggedToWordForTagAndSmiBits: {
9091cb0ef41Sopenharmony_ci      NodeMatcher m(node->InputAt(0));
9101cb0ef41Sopenharmony_ci      if (m.IsBitcastWordToTaggedSigned()) {
9111cb0ef41Sopenharmony_ci        RelaxEffectsAndControls(node);
9121cb0ef41Sopenharmony_ci        return Replace(m.InputAt(0));
9131cb0ef41Sopenharmony_ci      }
9141cb0ef41Sopenharmony_ci      break;
9151cb0ef41Sopenharmony_ci    }
9161cb0ef41Sopenharmony_ci    case IrOpcode::kBranch:
9171cb0ef41Sopenharmony_ci    case IrOpcode::kDeoptimizeIf:
9181cb0ef41Sopenharmony_ci    case IrOpcode::kDeoptimizeUnless:
9191cb0ef41Sopenharmony_ci    case IrOpcode::kTrapIf:
9201cb0ef41Sopenharmony_ci    case IrOpcode::kTrapUnless:
9211cb0ef41Sopenharmony_ci      return ReduceConditional(node);
9221cb0ef41Sopenharmony_ci    case IrOpcode::kInt64LessThan: {
9231cb0ef41Sopenharmony_ci      Int64BinopMatcher m(node);
9241cb0ef41Sopenharmony_ci      if (m.IsFoldable()) {  // K < K => K  (K stands for arbitrary constants)
9251cb0ef41Sopenharmony_ci        return ReplaceBool(m.left().ResolvedValue() <
9261cb0ef41Sopenharmony_ci                           m.right().ResolvedValue());
9271cb0ef41Sopenharmony_ci      }
9281cb0ef41Sopenharmony_ci      return ReduceWord64Comparisons(node);
9291cb0ef41Sopenharmony_ci    }
9301cb0ef41Sopenharmony_ci    case IrOpcode::kInt64LessThanOrEqual: {
9311cb0ef41Sopenharmony_ci      Int64BinopMatcher m(node);
9321cb0ef41Sopenharmony_ci      if (m.IsFoldable()) {  // K <= K => K  (K stands for arbitrary constants)
9331cb0ef41Sopenharmony_ci        return ReplaceBool(m.left().ResolvedValue() <=
9341cb0ef41Sopenharmony_ci                           m.right().ResolvedValue());
9351cb0ef41Sopenharmony_ci      }
9361cb0ef41Sopenharmony_ci      return ReduceWord64Comparisons(node);
9371cb0ef41Sopenharmony_ci    }
9381cb0ef41Sopenharmony_ci    case IrOpcode::kUint64LessThan: {
9391cb0ef41Sopenharmony_ci      Uint64BinopMatcher m(node);
9401cb0ef41Sopenharmony_ci      if (m.IsFoldable()) {  // K < K => K  (K stands for arbitrary constants)
9411cb0ef41Sopenharmony_ci        return ReplaceBool(m.left().ResolvedValue() <
9421cb0ef41Sopenharmony_ci                           m.right().ResolvedValue());
9431cb0ef41Sopenharmony_ci      }
9441cb0ef41Sopenharmony_ci      return ReduceWord64Comparisons(node);
9451cb0ef41Sopenharmony_ci    }
9461cb0ef41Sopenharmony_ci    case IrOpcode::kUint64LessThanOrEqual: {
9471cb0ef41Sopenharmony_ci      Uint64BinopMatcher m(node);
9481cb0ef41Sopenharmony_ci      if (m.IsFoldable()) {  // K <= K => K  (K stands for arbitrary constants)
9491cb0ef41Sopenharmony_ci        return ReplaceBool(m.left().ResolvedValue() <=
9501cb0ef41Sopenharmony_ci                           m.right().ResolvedValue());
9511cb0ef41Sopenharmony_ci      }
9521cb0ef41Sopenharmony_ci      return ReduceWord64Comparisons(node);
9531cb0ef41Sopenharmony_ci    }
9541cb0ef41Sopenharmony_ci    case IrOpcode::kFloat32Select:
9551cb0ef41Sopenharmony_ci    case IrOpcode::kFloat64Select:
9561cb0ef41Sopenharmony_ci    case IrOpcode::kWord32Select:
9571cb0ef41Sopenharmony_ci    case IrOpcode::kWord64Select: {
9581cb0ef41Sopenharmony_ci      Int32Matcher match(node->InputAt(0));
9591cb0ef41Sopenharmony_ci      if (match.HasResolvedValue()) {
9601cb0ef41Sopenharmony_ci        if (match.Is(0)) {
9611cb0ef41Sopenharmony_ci          return Replace(node->InputAt(2));
9621cb0ef41Sopenharmony_ci        } else {
9631cb0ef41Sopenharmony_ci          return Replace(node->InputAt(1));
9641cb0ef41Sopenharmony_ci        }
9651cb0ef41Sopenharmony_ci      }
9661cb0ef41Sopenharmony_ci      break;
9671cb0ef41Sopenharmony_ci    }
9681cb0ef41Sopenharmony_ci    default:
9691cb0ef41Sopenharmony_ci      break;
9701cb0ef41Sopenharmony_ci  }
9711cb0ef41Sopenharmony_ci  return NoChange();
9721cb0ef41Sopenharmony_ci}
9731cb0ef41Sopenharmony_ci
9741cb0ef41Sopenharmony_ciReduction MachineOperatorReducer::ReduceTruncateInt64ToInt32(Node* node) {
9751cb0ef41Sopenharmony_ci  Int64Matcher m(node->InputAt(0));
9761cb0ef41Sopenharmony_ci  if (m.HasResolvedValue())
9771cb0ef41Sopenharmony_ci    return ReplaceInt32(static_cast<int32_t>(m.ResolvedValue()));
9781cb0ef41Sopenharmony_ci  if (m.IsChangeInt32ToInt64()) return Replace(m.node()->InputAt(0));
9791cb0ef41Sopenharmony_ci  return NoChange();
9801cb0ef41Sopenharmony_ci}
9811cb0ef41Sopenharmony_ci
9821cb0ef41Sopenharmony_ciReduction MachineOperatorReducer::ReduceInt32Add(Node* node) {
9831cb0ef41Sopenharmony_ci  DCHECK_EQ(IrOpcode::kInt32Add, node->opcode());
9841cb0ef41Sopenharmony_ci  Int32BinopMatcher m(node);
9851cb0ef41Sopenharmony_ci  if (m.right().Is(0)) return Replace(m.left().node());  // x + 0 => x
9861cb0ef41Sopenharmony_ci  if (m.IsFoldable()) {  // K + K => K  (K stands for arbitrary constants)
9871cb0ef41Sopenharmony_ci    return ReplaceInt32(base::AddWithWraparound(m.left().ResolvedValue(),
9881cb0ef41Sopenharmony_ci                                                m.right().ResolvedValue()));
9891cb0ef41Sopenharmony_ci  }
9901cb0ef41Sopenharmony_ci  if (m.left().IsInt32Sub()) {
9911cb0ef41Sopenharmony_ci    Int32BinopMatcher mleft(m.left().node());
9921cb0ef41Sopenharmony_ci    if (mleft.left().Is(0)) {  // (0 - x) + y => y - x
9931cb0ef41Sopenharmony_ci      node->ReplaceInput(0, m.right().node());
9941cb0ef41Sopenharmony_ci      node->ReplaceInput(1, mleft.right().node());
9951cb0ef41Sopenharmony_ci      NodeProperties::ChangeOp(node, machine()->Int32Sub());
9961cb0ef41Sopenharmony_ci      return Changed(node).FollowedBy(ReduceInt32Sub(node));
9971cb0ef41Sopenharmony_ci    }
9981cb0ef41Sopenharmony_ci  }
9991cb0ef41Sopenharmony_ci  if (m.right().IsInt32Sub()) {
10001cb0ef41Sopenharmony_ci    Int32BinopMatcher mright(m.right().node());
10011cb0ef41Sopenharmony_ci    if (mright.left().Is(0)) {  // y + (0 - x) => y - x
10021cb0ef41Sopenharmony_ci      node->ReplaceInput(1, mright.right().node());
10031cb0ef41Sopenharmony_ci      NodeProperties::ChangeOp(node, machine()->Int32Sub());
10041cb0ef41Sopenharmony_ci      return Changed(node).FollowedBy(ReduceInt32Sub(node));
10051cb0ef41Sopenharmony_ci    }
10061cb0ef41Sopenharmony_ci  }
10071cb0ef41Sopenharmony_ci  // (x + Int32Constant(a)) + Int32Constant(b)) => x + Int32Constant(a + b)
10081cb0ef41Sopenharmony_ci  if (m.right().HasResolvedValue() && m.left().IsInt32Add()) {
10091cb0ef41Sopenharmony_ci    Int32BinopMatcher n(m.left().node());
10101cb0ef41Sopenharmony_ci    if (n.right().HasResolvedValue() && m.OwnsInput(m.left().node())) {
10111cb0ef41Sopenharmony_ci      node->ReplaceInput(
10121cb0ef41Sopenharmony_ci          1, Int32Constant(base::AddWithWraparound(m.right().ResolvedValue(),
10131cb0ef41Sopenharmony_ci                                                   n.right().ResolvedValue())));
10141cb0ef41Sopenharmony_ci      node->ReplaceInput(0, n.left().node());
10151cb0ef41Sopenharmony_ci      return Changed(node);
10161cb0ef41Sopenharmony_ci    }
10171cb0ef41Sopenharmony_ci  }
10181cb0ef41Sopenharmony_ci
10191cb0ef41Sopenharmony_ci  return NoChange();
10201cb0ef41Sopenharmony_ci}
10211cb0ef41Sopenharmony_ci
10221cb0ef41Sopenharmony_ciReduction MachineOperatorReducer::ReduceInt64Add(Node* node) {
10231cb0ef41Sopenharmony_ci  DCHECK_EQ(IrOpcode::kInt64Add, node->opcode());
10241cb0ef41Sopenharmony_ci  Int64BinopMatcher m(node);
10251cb0ef41Sopenharmony_ci  if (m.right().Is(0)) return Replace(m.left().node());  // x + 0 => 0
10261cb0ef41Sopenharmony_ci  if (m.IsFoldable()) {
10271cb0ef41Sopenharmony_ci    return ReplaceInt64(base::AddWithWraparound(m.left().ResolvedValue(),
10281cb0ef41Sopenharmony_ci                                                m.right().ResolvedValue()));
10291cb0ef41Sopenharmony_ci  }
10301cb0ef41Sopenharmony_ci  // (x + Int64Constant(a)) + Int64Constant(b) => x + Int64Constant(a + b)
10311cb0ef41Sopenharmony_ci  if (m.right().HasResolvedValue() && m.left().IsInt64Add()) {
10321cb0ef41Sopenharmony_ci    Int64BinopMatcher n(m.left().node());
10331cb0ef41Sopenharmony_ci    if (n.right().HasResolvedValue() && m.OwnsInput(m.left().node())) {
10341cb0ef41Sopenharmony_ci      node->ReplaceInput(
10351cb0ef41Sopenharmony_ci          1, Int64Constant(base::AddWithWraparound(m.right().ResolvedValue(),
10361cb0ef41Sopenharmony_ci                                                   n.right().ResolvedValue())));
10371cb0ef41Sopenharmony_ci      node->ReplaceInput(0, n.left().node());
10381cb0ef41Sopenharmony_ci      return Changed(node);
10391cb0ef41Sopenharmony_ci    }
10401cb0ef41Sopenharmony_ci  }
10411cb0ef41Sopenharmony_ci  return NoChange();
10421cb0ef41Sopenharmony_ci}
10431cb0ef41Sopenharmony_ci
10441cb0ef41Sopenharmony_ciReduction MachineOperatorReducer::ReduceInt32Sub(Node* node) {
10451cb0ef41Sopenharmony_ci  DCHECK_EQ(IrOpcode::kInt32Sub, node->opcode());
10461cb0ef41Sopenharmony_ci  Int32BinopMatcher m(node);
10471cb0ef41Sopenharmony_ci  if (m.right().Is(0)) return Replace(m.left().node());  // x - 0 => x
10481cb0ef41Sopenharmony_ci  if (m.IsFoldable()) {  // K - K => K  (K stands for arbitrary constants)
10491cb0ef41Sopenharmony_ci    return ReplaceInt32(base::SubWithWraparound(m.left().ResolvedValue(),
10501cb0ef41Sopenharmony_ci                                                m.right().ResolvedValue()));
10511cb0ef41Sopenharmony_ci  }
10521cb0ef41Sopenharmony_ci  if (m.LeftEqualsRight()) return ReplaceInt32(0);  // x - x => 0
10531cb0ef41Sopenharmony_ci  if (m.right().HasResolvedValue()) {               // x - K => x + -K
10541cb0ef41Sopenharmony_ci    node->ReplaceInput(
10551cb0ef41Sopenharmony_ci        1,
10561cb0ef41Sopenharmony_ci        Int32Constant(base::NegateWithWraparound(m.right().ResolvedValue())));
10571cb0ef41Sopenharmony_ci    NodeProperties::ChangeOp(node, machine()->Int32Add());
10581cb0ef41Sopenharmony_ci    return Changed(node).FollowedBy(ReduceInt32Add(node));
10591cb0ef41Sopenharmony_ci  }
10601cb0ef41Sopenharmony_ci  return NoChange();
10611cb0ef41Sopenharmony_ci}
10621cb0ef41Sopenharmony_ci
10631cb0ef41Sopenharmony_ciReduction MachineOperatorReducer::ReduceInt64Sub(Node* node) {
10641cb0ef41Sopenharmony_ci  DCHECK_EQ(IrOpcode::kInt64Sub, node->opcode());
10651cb0ef41Sopenharmony_ci  Int64BinopMatcher m(node);
10661cb0ef41Sopenharmony_ci  if (m.right().Is(0)) return Replace(m.left().node());  // x - 0 => x
10671cb0ef41Sopenharmony_ci  if (m.IsFoldable()) {  // K - K => K  (K stands for arbitrary constants)
10681cb0ef41Sopenharmony_ci    return ReplaceInt64(base::SubWithWraparound(m.left().ResolvedValue(),
10691cb0ef41Sopenharmony_ci                                                m.right().ResolvedValue()));
10701cb0ef41Sopenharmony_ci  }
10711cb0ef41Sopenharmony_ci  if (m.LeftEqualsRight()) return Replace(Int64Constant(0));  // x - x => 0
10721cb0ef41Sopenharmony_ci  if (m.right().HasResolvedValue()) {                         // x - K => x + -K
10731cb0ef41Sopenharmony_ci    node->ReplaceInput(
10741cb0ef41Sopenharmony_ci        1,
10751cb0ef41Sopenharmony_ci        Int64Constant(base::NegateWithWraparound(m.right().ResolvedValue())));
10761cb0ef41Sopenharmony_ci    NodeProperties::ChangeOp(node, machine()->Int64Add());
10771cb0ef41Sopenharmony_ci    return Changed(node).FollowedBy(ReduceInt64Add(node));
10781cb0ef41Sopenharmony_ci  }
10791cb0ef41Sopenharmony_ci  return NoChange();
10801cb0ef41Sopenharmony_ci}
10811cb0ef41Sopenharmony_ci
10821cb0ef41Sopenharmony_ciReduction MachineOperatorReducer::ReduceInt64Mul(Node* node) {
10831cb0ef41Sopenharmony_ci  DCHECK_EQ(IrOpcode::kInt64Mul, node->opcode());
10841cb0ef41Sopenharmony_ci  Int64BinopMatcher m(node);
10851cb0ef41Sopenharmony_ci  if (m.right().Is(0)) return Replace(m.right().node());  // x * 0 => 0
10861cb0ef41Sopenharmony_ci  if (m.right().Is(1)) return Replace(m.left().node());   // x * 1 => x
10871cb0ef41Sopenharmony_ci  if (m.IsFoldable()) {  // K * K => K  (K stands for arbitrary constants)
10881cb0ef41Sopenharmony_ci    return ReplaceInt64(base::MulWithWraparound(m.left().ResolvedValue(),
10891cb0ef41Sopenharmony_ci                                                m.right().ResolvedValue()));
10901cb0ef41Sopenharmony_ci  }
10911cb0ef41Sopenharmony_ci  if (m.right().Is(-1)) {  // x * -1 => 0 - x
10921cb0ef41Sopenharmony_ci    node->ReplaceInput(0, Int64Constant(0));
10931cb0ef41Sopenharmony_ci    node->ReplaceInput(1, m.left().node());
10941cb0ef41Sopenharmony_ci    NodeProperties::ChangeOp(node, machine()->Int64Sub());
10951cb0ef41Sopenharmony_ci    return Changed(node);
10961cb0ef41Sopenharmony_ci  }
10971cb0ef41Sopenharmony_ci  if (m.right().IsPowerOf2()) {  // x * 2^n => x << n
10981cb0ef41Sopenharmony_ci    node->ReplaceInput(
10991cb0ef41Sopenharmony_ci        1,
11001cb0ef41Sopenharmony_ci        Int64Constant(base::bits::WhichPowerOfTwo(m.right().ResolvedValue())));
11011cb0ef41Sopenharmony_ci    NodeProperties::ChangeOp(node, machine()->Word64Shl());
11021cb0ef41Sopenharmony_ci    return Changed(node).FollowedBy(ReduceWord64Shl(node));
11031cb0ef41Sopenharmony_ci  }
11041cb0ef41Sopenharmony_ci  // (x * Int64Constant(a)) * Int64Constant(b)) => x * Int64Constant(a * b)
11051cb0ef41Sopenharmony_ci  if (m.right().HasResolvedValue() && m.left().IsInt64Mul()) {
11061cb0ef41Sopenharmony_ci    Int64BinopMatcher n(m.left().node());
11071cb0ef41Sopenharmony_ci    if (n.right().HasResolvedValue() && m.OwnsInput(m.left().node())) {
11081cb0ef41Sopenharmony_ci      node->ReplaceInput(
11091cb0ef41Sopenharmony_ci          1, Int64Constant(base::MulWithWraparound(m.right().ResolvedValue(),
11101cb0ef41Sopenharmony_ci                                                   n.right().ResolvedValue())));
11111cb0ef41Sopenharmony_ci      node->ReplaceInput(0, n.left().node());
11121cb0ef41Sopenharmony_ci      return Changed(node);
11131cb0ef41Sopenharmony_ci    }
11141cb0ef41Sopenharmony_ci  }
11151cb0ef41Sopenharmony_ci  return NoChange();
11161cb0ef41Sopenharmony_ci}
11171cb0ef41Sopenharmony_ci
11181cb0ef41Sopenharmony_ciReduction MachineOperatorReducer::ReduceInt32Div(Node* node) {
11191cb0ef41Sopenharmony_ci  Int32BinopMatcher m(node);
11201cb0ef41Sopenharmony_ci  if (m.left().Is(0)) return Replace(m.left().node());    // 0 / x => 0
11211cb0ef41Sopenharmony_ci  if (m.right().Is(0)) return Replace(m.right().node());  // x / 0 => 0
11221cb0ef41Sopenharmony_ci  if (m.right().Is(1)) return Replace(m.left().node());   // x / 1 => x
11231cb0ef41Sopenharmony_ci  if (m.IsFoldable()) {  // K / K => K  (K stands for arbitrary constants)
11241cb0ef41Sopenharmony_ci    return ReplaceInt32(base::bits::SignedDiv32(m.left().ResolvedValue(),
11251cb0ef41Sopenharmony_ci                                                m.right().ResolvedValue()));
11261cb0ef41Sopenharmony_ci  }
11271cb0ef41Sopenharmony_ci  if (m.LeftEqualsRight()) {  // x / x => x != 0
11281cb0ef41Sopenharmony_ci    Node* const zero = Int32Constant(0);
11291cb0ef41Sopenharmony_ci    return Replace(Word32Equal(Word32Equal(m.left().node(), zero), zero));
11301cb0ef41Sopenharmony_ci  }
11311cb0ef41Sopenharmony_ci  if (m.right().Is(-1)) {  // x / -1 => 0 - x
11321cb0ef41Sopenharmony_ci    node->ReplaceInput(0, Int32Constant(0));
11331cb0ef41Sopenharmony_ci    node->ReplaceInput(1, m.left().node());
11341cb0ef41Sopenharmony_ci    node->TrimInputCount(2);
11351cb0ef41Sopenharmony_ci    NodeProperties::ChangeOp(node, machine()->Int32Sub());
11361cb0ef41Sopenharmony_ci    return Changed(node);
11371cb0ef41Sopenharmony_ci  }
11381cb0ef41Sopenharmony_ci  if (m.right().HasResolvedValue()) {
11391cb0ef41Sopenharmony_ci    int32_t const divisor = m.right().ResolvedValue();
11401cb0ef41Sopenharmony_ci    Node* const dividend = m.left().node();
11411cb0ef41Sopenharmony_ci    Node* quotient = dividend;
11421cb0ef41Sopenharmony_ci    if (base::bits::IsPowerOfTwo(Abs(divisor))) {
11431cb0ef41Sopenharmony_ci      uint32_t const shift = base::bits::WhichPowerOfTwo(Abs(divisor));
11441cb0ef41Sopenharmony_ci      DCHECK_NE(0u, shift);
11451cb0ef41Sopenharmony_ci      if (shift > 1) {
11461cb0ef41Sopenharmony_ci        quotient = Word32Sar(quotient, 31);
11471cb0ef41Sopenharmony_ci      }
11481cb0ef41Sopenharmony_ci      quotient = Int32Add(Word32Shr(quotient, 32u - shift), dividend);
11491cb0ef41Sopenharmony_ci      quotient = Word32Sar(quotient, shift);
11501cb0ef41Sopenharmony_ci    } else {
11511cb0ef41Sopenharmony_ci      quotient = Int32Div(quotient, Abs(divisor));
11521cb0ef41Sopenharmony_ci    }
11531cb0ef41Sopenharmony_ci    if (divisor < 0) {
11541cb0ef41Sopenharmony_ci      node->ReplaceInput(0, Int32Constant(0));
11551cb0ef41Sopenharmony_ci      node->ReplaceInput(1, quotient);
11561cb0ef41Sopenharmony_ci      node->TrimInputCount(2);
11571cb0ef41Sopenharmony_ci      NodeProperties::ChangeOp(node, machine()->Int32Sub());
11581cb0ef41Sopenharmony_ci      return Changed(node);
11591cb0ef41Sopenharmony_ci    }
11601cb0ef41Sopenharmony_ci    return Replace(quotient);
11611cb0ef41Sopenharmony_ci  }
11621cb0ef41Sopenharmony_ci  return NoChange();
11631cb0ef41Sopenharmony_ci}
11641cb0ef41Sopenharmony_ci
11651cb0ef41Sopenharmony_ciReduction MachineOperatorReducer::ReduceUint32Div(Node* node) {
11661cb0ef41Sopenharmony_ci  Uint32BinopMatcher m(node);
11671cb0ef41Sopenharmony_ci  if (m.left().Is(0)) return Replace(m.left().node());    // 0 / x => 0
11681cb0ef41Sopenharmony_ci  if (m.right().Is(0)) return Replace(m.right().node());  // x / 0 => 0
11691cb0ef41Sopenharmony_ci  if (m.right().Is(1)) return Replace(m.left().node());   // x / 1 => x
11701cb0ef41Sopenharmony_ci  if (m.IsFoldable()) {  // K / K => K  (K stands for arbitrary constants)
11711cb0ef41Sopenharmony_ci    return ReplaceUint32(base::bits::UnsignedDiv32(m.left().ResolvedValue(),
11721cb0ef41Sopenharmony_ci                                                   m.right().ResolvedValue()));
11731cb0ef41Sopenharmony_ci  }
11741cb0ef41Sopenharmony_ci  if (m.LeftEqualsRight()) {  // x / x => x != 0
11751cb0ef41Sopenharmony_ci    Node* const zero = Int32Constant(0);
11761cb0ef41Sopenharmony_ci    return Replace(Word32Equal(Word32Equal(m.left().node(), zero), zero));
11771cb0ef41Sopenharmony_ci  }
11781cb0ef41Sopenharmony_ci  if (m.right().HasResolvedValue()) {
11791cb0ef41Sopenharmony_ci    Node* const dividend = m.left().node();
11801cb0ef41Sopenharmony_ci    uint32_t const divisor = m.right().ResolvedValue();
11811cb0ef41Sopenharmony_ci    if (base::bits::IsPowerOfTwo(divisor)) {  // x / 2^n => x >> n
11821cb0ef41Sopenharmony_ci      node->ReplaceInput(1, Uint32Constant(base::bits::WhichPowerOfTwo(
11831cb0ef41Sopenharmony_ci                                m.right().ResolvedValue())));
11841cb0ef41Sopenharmony_ci      node->TrimInputCount(2);
11851cb0ef41Sopenharmony_ci      NodeProperties::ChangeOp(node, machine()->Word32Shr());
11861cb0ef41Sopenharmony_ci      return Changed(node);
11871cb0ef41Sopenharmony_ci    } else {
11881cb0ef41Sopenharmony_ci      return Replace(Uint32Div(dividend, divisor));
11891cb0ef41Sopenharmony_ci    }
11901cb0ef41Sopenharmony_ci  }
11911cb0ef41Sopenharmony_ci  return NoChange();
11921cb0ef41Sopenharmony_ci}
11931cb0ef41Sopenharmony_ci
11941cb0ef41Sopenharmony_ciReduction MachineOperatorReducer::ReduceInt32Mod(Node* node) {
11951cb0ef41Sopenharmony_ci  Int32BinopMatcher m(node);
11961cb0ef41Sopenharmony_ci  if (m.left().Is(0)) return Replace(m.left().node());    // 0 % x  => 0
11971cb0ef41Sopenharmony_ci  if (m.right().Is(0)) return Replace(m.right().node());  // x % 0  => 0
11981cb0ef41Sopenharmony_ci  if (m.right().Is(1)) return ReplaceInt32(0);            // x % 1  => 0
11991cb0ef41Sopenharmony_ci  if (m.right().Is(-1)) return ReplaceInt32(0);           // x % -1 => 0
12001cb0ef41Sopenharmony_ci  if (m.LeftEqualsRight()) return ReplaceInt32(0);        // x % x  => 0
12011cb0ef41Sopenharmony_ci  if (m.IsFoldable()) {  // K % K => K  (K stands for arbitrary constants)
12021cb0ef41Sopenharmony_ci    return ReplaceInt32(base::bits::SignedMod32(m.left().ResolvedValue(),
12031cb0ef41Sopenharmony_ci                                                m.right().ResolvedValue()));
12041cb0ef41Sopenharmony_ci  }
12051cb0ef41Sopenharmony_ci  if (m.right().HasResolvedValue()) {
12061cb0ef41Sopenharmony_ci    Node* const dividend = m.left().node();
12071cb0ef41Sopenharmony_ci    uint32_t const divisor = Abs(m.right().ResolvedValue());
12081cb0ef41Sopenharmony_ci    if (base::bits::IsPowerOfTwo(divisor)) {
12091cb0ef41Sopenharmony_ci      uint32_t const mask = divisor - 1;
12101cb0ef41Sopenharmony_ci      Node* const zero = Int32Constant(0);
12111cb0ef41Sopenharmony_ci      Diamond d(graph(), common(),
12121cb0ef41Sopenharmony_ci                graph()->NewNode(machine()->Int32LessThan(), dividend, zero),
12131cb0ef41Sopenharmony_ci                BranchHint::kFalse);
12141cb0ef41Sopenharmony_ci      return Replace(
12151cb0ef41Sopenharmony_ci          d.Phi(MachineRepresentation::kWord32,
12161cb0ef41Sopenharmony_ci                Int32Sub(zero, Word32And(Int32Sub(zero, dividend), mask)),
12171cb0ef41Sopenharmony_ci                Word32And(dividend, mask)));
12181cb0ef41Sopenharmony_ci    } else {
12191cb0ef41Sopenharmony_ci      Node* quotient = Int32Div(dividend, divisor);
12201cb0ef41Sopenharmony_ci      DCHECK_EQ(dividend, node->InputAt(0));
12211cb0ef41Sopenharmony_ci      node->ReplaceInput(1, Int32Mul(quotient, Int32Constant(divisor)));
12221cb0ef41Sopenharmony_ci      node->TrimInputCount(2);
12231cb0ef41Sopenharmony_ci      NodeProperties::ChangeOp(node, machine()->Int32Sub());
12241cb0ef41Sopenharmony_ci    }
12251cb0ef41Sopenharmony_ci    return Changed(node);
12261cb0ef41Sopenharmony_ci  }
12271cb0ef41Sopenharmony_ci  return NoChange();
12281cb0ef41Sopenharmony_ci}
12291cb0ef41Sopenharmony_ci
12301cb0ef41Sopenharmony_ciReduction MachineOperatorReducer::ReduceUint32Mod(Node* node) {
12311cb0ef41Sopenharmony_ci  Uint32BinopMatcher m(node);
12321cb0ef41Sopenharmony_ci  if (m.left().Is(0)) return Replace(m.left().node());    // 0 % x => 0
12331cb0ef41Sopenharmony_ci  if (m.right().Is(0)) return Replace(m.right().node());  // x % 0 => 0
12341cb0ef41Sopenharmony_ci  if (m.right().Is(1)) return ReplaceUint32(0);           // x % 1 => 0
12351cb0ef41Sopenharmony_ci  if (m.LeftEqualsRight()) return ReplaceInt32(0);        // x % x  => 0
12361cb0ef41Sopenharmony_ci  if (m.IsFoldable()) {  // K % K => K  (K stands for arbitrary constants)
12371cb0ef41Sopenharmony_ci    return ReplaceUint32(base::bits::UnsignedMod32(m.left().ResolvedValue(),
12381cb0ef41Sopenharmony_ci                                                   m.right().ResolvedValue()));
12391cb0ef41Sopenharmony_ci  }
12401cb0ef41Sopenharmony_ci  if (m.right().HasResolvedValue()) {
12411cb0ef41Sopenharmony_ci    Node* const dividend = m.left().node();
12421cb0ef41Sopenharmony_ci    uint32_t const divisor = m.right().ResolvedValue();
12431cb0ef41Sopenharmony_ci    if (base::bits::IsPowerOfTwo(divisor)) {  // x % 2^n => x & 2^n-1
12441cb0ef41Sopenharmony_ci      node->ReplaceInput(1, Uint32Constant(m.right().ResolvedValue() - 1));
12451cb0ef41Sopenharmony_ci      node->TrimInputCount(2);
12461cb0ef41Sopenharmony_ci      NodeProperties::ChangeOp(node, machine()->Word32And());
12471cb0ef41Sopenharmony_ci    } else {
12481cb0ef41Sopenharmony_ci      Node* quotient = Uint32Div(dividend, divisor);
12491cb0ef41Sopenharmony_ci      DCHECK_EQ(dividend, node->InputAt(0));
12501cb0ef41Sopenharmony_ci      node->ReplaceInput(1, Int32Mul(quotient, Uint32Constant(divisor)));
12511cb0ef41Sopenharmony_ci      node->TrimInputCount(2);
12521cb0ef41Sopenharmony_ci      NodeProperties::ChangeOp(node, machine()->Int32Sub());
12531cb0ef41Sopenharmony_ci    }
12541cb0ef41Sopenharmony_ci    return Changed(node);
12551cb0ef41Sopenharmony_ci  }
12561cb0ef41Sopenharmony_ci  return NoChange();
12571cb0ef41Sopenharmony_ci}
12581cb0ef41Sopenharmony_ci
12591cb0ef41Sopenharmony_ciReduction MachineOperatorReducer::ReduceStore(Node* node) {
12601cb0ef41Sopenharmony_ci  NodeMatcher nm(node);
12611cb0ef41Sopenharmony_ci  DCHECK(nm.IsStore() || nm.IsUnalignedStore());
12621cb0ef41Sopenharmony_ci  MachineRepresentation rep =
12631cb0ef41Sopenharmony_ci      nm.IsStore() ? StoreRepresentationOf(node->op()).representation()
12641cb0ef41Sopenharmony_ci                   : UnalignedStoreRepresentationOf(node->op());
12651cb0ef41Sopenharmony_ci
12661cb0ef41Sopenharmony_ci  const int value_input = 2;
12671cb0ef41Sopenharmony_ci  Node* const value = node->InputAt(value_input);
12681cb0ef41Sopenharmony_ci
12691cb0ef41Sopenharmony_ci  switch (value->opcode()) {
12701cb0ef41Sopenharmony_ci    case IrOpcode::kWord32And: {
12711cb0ef41Sopenharmony_ci      Uint32BinopMatcher m(value);
12721cb0ef41Sopenharmony_ci      if (m.right().HasResolvedValue() &&
12731cb0ef41Sopenharmony_ci          ((rep == MachineRepresentation::kWord8 &&
12741cb0ef41Sopenharmony_ci            (m.right().ResolvedValue() & 0xFF) == 0xFF) ||
12751cb0ef41Sopenharmony_ci           (rep == MachineRepresentation::kWord16 &&
12761cb0ef41Sopenharmony_ci            (m.right().ResolvedValue() & 0xFFFF) == 0xFFFF))) {
12771cb0ef41Sopenharmony_ci        node->ReplaceInput(value_input, m.left().node());
12781cb0ef41Sopenharmony_ci        return Changed(node);
12791cb0ef41Sopenharmony_ci      }
12801cb0ef41Sopenharmony_ci      break;
12811cb0ef41Sopenharmony_ci    }
12821cb0ef41Sopenharmony_ci    case IrOpcode::kWord32Sar: {
12831cb0ef41Sopenharmony_ci      Int32BinopMatcher m(value);
12841cb0ef41Sopenharmony_ci      if (m.left().IsWord32Shl() && ((rep == MachineRepresentation::kWord8 &&
12851cb0ef41Sopenharmony_ci                                      m.right().IsInRange(1, 24)) ||
12861cb0ef41Sopenharmony_ci                                     (rep == MachineRepresentation::kWord16 &&
12871cb0ef41Sopenharmony_ci                                      m.right().IsInRange(1, 16)))) {
12881cb0ef41Sopenharmony_ci        Int32BinopMatcher mleft(m.left().node());
12891cb0ef41Sopenharmony_ci        if (mleft.right().Is(m.right().ResolvedValue())) {
12901cb0ef41Sopenharmony_ci          node->ReplaceInput(value_input, mleft.left().node());
12911cb0ef41Sopenharmony_ci          return Changed(node);
12921cb0ef41Sopenharmony_ci        }
12931cb0ef41Sopenharmony_ci      }
12941cb0ef41Sopenharmony_ci      break;
12951cb0ef41Sopenharmony_ci    }
12961cb0ef41Sopenharmony_ci    default:
12971cb0ef41Sopenharmony_ci      break;
12981cb0ef41Sopenharmony_ci  }
12991cb0ef41Sopenharmony_ci  return NoChange();
13001cb0ef41Sopenharmony_ci}
13011cb0ef41Sopenharmony_ci
13021cb0ef41Sopenharmony_ciReduction MachineOperatorReducer::ReduceProjection(size_t index, Node* node) {
13031cb0ef41Sopenharmony_ci  switch (node->opcode()) {
13041cb0ef41Sopenharmony_ci    case IrOpcode::kInt32AddWithOverflow: {
13051cb0ef41Sopenharmony_ci      DCHECK(index == 0 || index == 1);
13061cb0ef41Sopenharmony_ci      Int32BinopMatcher m(node);
13071cb0ef41Sopenharmony_ci      if (m.IsFoldable()) {
13081cb0ef41Sopenharmony_ci        int32_t val;
13091cb0ef41Sopenharmony_ci        bool ovf = base::bits::SignedAddOverflow32(
13101cb0ef41Sopenharmony_ci            m.left().ResolvedValue(), m.right().ResolvedValue(), &val);
13111cb0ef41Sopenharmony_ci        return ReplaceInt32(index == 0 ? val : ovf);
13121cb0ef41Sopenharmony_ci      }
13131cb0ef41Sopenharmony_ci      if (m.right().Is(0)) {
13141cb0ef41Sopenharmony_ci        return Replace(index == 0 ? m.left().node() : m.right().node());
13151cb0ef41Sopenharmony_ci      }
13161cb0ef41Sopenharmony_ci      break;
13171cb0ef41Sopenharmony_ci    }
13181cb0ef41Sopenharmony_ci    case IrOpcode::kInt32SubWithOverflow: {
13191cb0ef41Sopenharmony_ci      DCHECK(index == 0 || index == 1);
13201cb0ef41Sopenharmony_ci      Int32BinopMatcher m(node);
13211cb0ef41Sopenharmony_ci      if (m.IsFoldable()) {
13221cb0ef41Sopenharmony_ci        int32_t val;
13231cb0ef41Sopenharmony_ci        bool ovf = base::bits::SignedSubOverflow32(
13241cb0ef41Sopenharmony_ci            m.left().ResolvedValue(), m.right().ResolvedValue(), &val);
13251cb0ef41Sopenharmony_ci        return ReplaceInt32(index == 0 ? val : ovf);
13261cb0ef41Sopenharmony_ci      }
13271cb0ef41Sopenharmony_ci      if (m.right().Is(0)) {
13281cb0ef41Sopenharmony_ci        return Replace(index == 0 ? m.left().node() : m.right().node());
13291cb0ef41Sopenharmony_ci      }
13301cb0ef41Sopenharmony_ci      break;
13311cb0ef41Sopenharmony_ci    }
13321cb0ef41Sopenharmony_ci    case IrOpcode::kInt32MulWithOverflow: {
13331cb0ef41Sopenharmony_ci      DCHECK(index == 0 || index == 1);
13341cb0ef41Sopenharmony_ci      Int32BinopMatcher m(node);
13351cb0ef41Sopenharmony_ci      if (m.IsFoldable()) {
13361cb0ef41Sopenharmony_ci        int32_t val;
13371cb0ef41Sopenharmony_ci        bool ovf = base::bits::SignedMulOverflow32(
13381cb0ef41Sopenharmony_ci            m.left().ResolvedValue(), m.right().ResolvedValue(), &val);
13391cb0ef41Sopenharmony_ci        return ReplaceInt32(index == 0 ? val : ovf);
13401cb0ef41Sopenharmony_ci      }
13411cb0ef41Sopenharmony_ci      if (m.right().Is(0)) {
13421cb0ef41Sopenharmony_ci        return Replace(m.right().node());
13431cb0ef41Sopenharmony_ci      }
13441cb0ef41Sopenharmony_ci      if (m.right().Is(1)) {
13451cb0ef41Sopenharmony_ci        return index == 0 ? Replace(m.left().node()) : ReplaceInt32(0);
13461cb0ef41Sopenharmony_ci      }
13471cb0ef41Sopenharmony_ci      break;
13481cb0ef41Sopenharmony_ci    }
13491cb0ef41Sopenharmony_ci    default:
13501cb0ef41Sopenharmony_ci      break;
13511cb0ef41Sopenharmony_ci  }
13521cb0ef41Sopenharmony_ci  return NoChange();
13531cb0ef41Sopenharmony_ci}
13541cb0ef41Sopenharmony_ci
13551cb0ef41Sopenharmony_cinamespace {
13561cb0ef41Sopenharmony_ci
13571cb0ef41Sopenharmony_ci// Returns true if "value << shift >> shift == value". This can be interpreted
13581cb0ef41Sopenharmony_ci// as "left shifting |value| by |shift| doesn't shift away significant bits".
13591cb0ef41Sopenharmony_ci// Or, equivalently, "left shifting |value| by |shift| doesn't have signed
13601cb0ef41Sopenharmony_ci// overflow".
13611cb0ef41Sopenharmony_cibool CanRevertLeftShiftWithRightShift(int32_t value, int32_t shift) {
13621cb0ef41Sopenharmony_ci  if (shift < 0 || shift >= 32) {
13631cb0ef41Sopenharmony_ci    // This shift would be UB in C++
13641cb0ef41Sopenharmony_ci    return false;
13651cb0ef41Sopenharmony_ci  }
13661cb0ef41Sopenharmony_ci  if (static_cast<int32_t>(static_cast<uint32_t>(value) << shift) >> shift !=
13671cb0ef41Sopenharmony_ci      static_cast<int32_t>(value)) {
13681cb0ef41Sopenharmony_ci    return false;
13691cb0ef41Sopenharmony_ci  }
13701cb0ef41Sopenharmony_ci  return true;
13711cb0ef41Sopenharmony_ci}
13721cb0ef41Sopenharmony_ci
13731cb0ef41Sopenharmony_ci}  // namespace
13741cb0ef41Sopenharmony_ci
13751cb0ef41Sopenharmony_ciReduction MachineOperatorReducer::ReduceWord32Comparisons(Node* node) {
13761cb0ef41Sopenharmony_ci  DCHECK(node->opcode() == IrOpcode::kInt32LessThan ||
13771cb0ef41Sopenharmony_ci         node->opcode() == IrOpcode::kInt32LessThanOrEqual ||
13781cb0ef41Sopenharmony_ci         node->opcode() == IrOpcode::kUint32LessThan ||
13791cb0ef41Sopenharmony_ci         node->opcode() == IrOpcode::kUint32LessThanOrEqual);
13801cb0ef41Sopenharmony_ci  Int32BinopMatcher m(node);
13811cb0ef41Sopenharmony_ci  // (x >> K) < (y >> K) => x < y   if only zeros shifted out
13821cb0ef41Sopenharmony_ci  if (m.left().op() == machine()->Word32SarShiftOutZeros() &&
13831cb0ef41Sopenharmony_ci      m.right().op() == machine()->Word32SarShiftOutZeros()) {
13841cb0ef41Sopenharmony_ci    Int32BinopMatcher mleft(m.left().node());
13851cb0ef41Sopenharmony_ci    Int32BinopMatcher mright(m.right().node());
13861cb0ef41Sopenharmony_ci    if (mleft.right().HasResolvedValue() &&
13871cb0ef41Sopenharmony_ci        mright.right().Is(mleft.right().ResolvedValue())) {
13881cb0ef41Sopenharmony_ci      node->ReplaceInput(0, mleft.left().node());
13891cb0ef41Sopenharmony_ci      node->ReplaceInput(1, mright.left().node());
13901cb0ef41Sopenharmony_ci      return Changed(node);
13911cb0ef41Sopenharmony_ci    }
13921cb0ef41Sopenharmony_ci  }
13931cb0ef41Sopenharmony_ci  // Simplifying (x >> n) <= k into x <= (k << n), with "k << n" being
13941cb0ef41Sopenharmony_ci  // computed here at compile time.
13951cb0ef41Sopenharmony_ci  if (m.right().HasResolvedValue() &&
13961cb0ef41Sopenharmony_ci      m.left().op() == machine()->Word32SarShiftOutZeros() &&
13971cb0ef41Sopenharmony_ci      m.left().node()->UseCount() == 1) {
13981cb0ef41Sopenharmony_ci    uint32_t right = m.right().ResolvedValue();
13991cb0ef41Sopenharmony_ci    Int32BinopMatcher mleft(m.left().node());
14001cb0ef41Sopenharmony_ci    if (mleft.right().HasResolvedValue()) {
14011cb0ef41Sopenharmony_ci      auto shift = mleft.right().ResolvedValue();
14021cb0ef41Sopenharmony_ci      if (CanRevertLeftShiftWithRightShift(right, shift)) {
14031cb0ef41Sopenharmony_ci        node->ReplaceInput(0, mleft.left().node());
14041cb0ef41Sopenharmony_ci        node->ReplaceInput(1, Int32Constant(right << shift));
14051cb0ef41Sopenharmony_ci        return Changed(node);
14061cb0ef41Sopenharmony_ci      }
14071cb0ef41Sopenharmony_ci    }
14081cb0ef41Sopenharmony_ci  }
14091cb0ef41Sopenharmony_ci  // Simplifying k <= (x >> n) into (k << n) <= x, with "k << n" being
14101cb0ef41Sopenharmony_ci  // computed here at compile time.
14111cb0ef41Sopenharmony_ci  if (m.left().HasResolvedValue() &&
14121cb0ef41Sopenharmony_ci      m.right().op() == machine()->Word32SarShiftOutZeros() &&
14131cb0ef41Sopenharmony_ci      m.right().node()->UseCount() == 1) {
14141cb0ef41Sopenharmony_ci    uint32_t left = m.left().ResolvedValue();
14151cb0ef41Sopenharmony_ci    Int32BinopMatcher mright(m.right().node());
14161cb0ef41Sopenharmony_ci    if (mright.right().HasResolvedValue()) {
14171cb0ef41Sopenharmony_ci      auto shift = mright.right().ResolvedValue();
14181cb0ef41Sopenharmony_ci      if (CanRevertLeftShiftWithRightShift(left, shift)) {
14191cb0ef41Sopenharmony_ci        node->ReplaceInput(0, Int32Constant(left << shift));
14201cb0ef41Sopenharmony_ci        node->ReplaceInput(1, mright.left().node());
14211cb0ef41Sopenharmony_ci        return Changed(node);
14221cb0ef41Sopenharmony_ci      }
14231cb0ef41Sopenharmony_ci    }
14241cb0ef41Sopenharmony_ci  }
14251cb0ef41Sopenharmony_ci  return NoChange();
14261cb0ef41Sopenharmony_ci}
14271cb0ef41Sopenharmony_ci
14281cb0ef41Sopenharmony_ciconst Operator* MachineOperatorReducer::Map64To32Comparison(
14291cb0ef41Sopenharmony_ci    const Operator* op, bool sign_extended) {
14301cb0ef41Sopenharmony_ci  switch (op->opcode()) {
14311cb0ef41Sopenharmony_ci    case IrOpcode::kInt64LessThan:
14321cb0ef41Sopenharmony_ci      return sign_extended ? machine()->Int32LessThan()
14331cb0ef41Sopenharmony_ci                           : machine()->Uint32LessThan();
14341cb0ef41Sopenharmony_ci    case IrOpcode::kInt64LessThanOrEqual:
14351cb0ef41Sopenharmony_ci      return sign_extended ? machine()->Int32LessThanOrEqual()
14361cb0ef41Sopenharmony_ci                           : machine()->Uint32LessThanOrEqual();
14371cb0ef41Sopenharmony_ci    case IrOpcode::kUint64LessThan:
14381cb0ef41Sopenharmony_ci      return machine()->Uint32LessThan();
14391cb0ef41Sopenharmony_ci    case IrOpcode::kUint64LessThanOrEqual:
14401cb0ef41Sopenharmony_ci      return machine()->Uint32LessThanOrEqual();
14411cb0ef41Sopenharmony_ci    default:
14421cb0ef41Sopenharmony_ci      UNREACHABLE();
14431cb0ef41Sopenharmony_ci  }
14441cb0ef41Sopenharmony_ci}
14451cb0ef41Sopenharmony_ci
14461cb0ef41Sopenharmony_ciReduction MachineOperatorReducer::ReduceWord64Comparisons(Node* node) {
14471cb0ef41Sopenharmony_ci  DCHECK(node->opcode() == IrOpcode::kInt64LessThan ||
14481cb0ef41Sopenharmony_ci         node->opcode() == IrOpcode::kInt64LessThanOrEqual ||
14491cb0ef41Sopenharmony_ci         node->opcode() == IrOpcode::kUint64LessThan ||
14501cb0ef41Sopenharmony_ci         node->opcode() == IrOpcode::kUint64LessThanOrEqual);
14511cb0ef41Sopenharmony_ci  Int64BinopMatcher m(node);
14521cb0ef41Sopenharmony_ci
14531cb0ef41Sopenharmony_ci  bool sign_extended =
14541cb0ef41Sopenharmony_ci      m.left().IsChangeInt32ToInt64() && m.right().IsChangeInt32ToInt64();
14551cb0ef41Sopenharmony_ci  if (sign_extended || (m.left().IsChangeUint32ToUint64() &&
14561cb0ef41Sopenharmony_ci                        m.right().IsChangeUint32ToUint64())) {
14571cb0ef41Sopenharmony_ci    node->ReplaceInput(0, NodeProperties::GetValueInput(m.left().node(), 0));
14581cb0ef41Sopenharmony_ci    node->ReplaceInput(1, NodeProperties::GetValueInput(m.right().node(), 0));
14591cb0ef41Sopenharmony_ci    NodeProperties::ChangeOp(node,
14601cb0ef41Sopenharmony_ci                             Map64To32Comparison(node->op(), sign_extended));
14611cb0ef41Sopenharmony_ci    return Changed(node).FollowedBy(Reduce(node));
14621cb0ef41Sopenharmony_ci  }
14631cb0ef41Sopenharmony_ci
14641cb0ef41Sopenharmony_ci  // (x >> K) < (y >> K) => x < y   if only zeros shifted out
14651cb0ef41Sopenharmony_ci  // This is useful for Smi untagging, which results in such a shift.
14661cb0ef41Sopenharmony_ci  if (m.left().op() == machine()->Word64SarShiftOutZeros() &&
14671cb0ef41Sopenharmony_ci      m.right().op() == machine()->Word64SarShiftOutZeros()) {
14681cb0ef41Sopenharmony_ci    Int64BinopMatcher mleft(m.left().node());
14691cb0ef41Sopenharmony_ci    Int64BinopMatcher mright(m.right().node());
14701cb0ef41Sopenharmony_ci    if (mleft.right().HasResolvedValue() &&
14711cb0ef41Sopenharmony_ci        mright.right().Is(mleft.right().ResolvedValue())) {
14721cb0ef41Sopenharmony_ci      node->ReplaceInput(0, mleft.left().node());
14731cb0ef41Sopenharmony_ci      node->ReplaceInput(1, mright.left().node());
14741cb0ef41Sopenharmony_ci      return Changed(node);
14751cb0ef41Sopenharmony_ci    }
14761cb0ef41Sopenharmony_ci  }
14771cb0ef41Sopenharmony_ci
14781cb0ef41Sopenharmony_ci  return NoChange();
14791cb0ef41Sopenharmony_ci}
14801cb0ef41Sopenharmony_ci
14811cb0ef41Sopenharmony_ciReduction MachineOperatorReducer::ReduceWord32Shifts(Node* node) {
14821cb0ef41Sopenharmony_ci  DCHECK((node->opcode() == IrOpcode::kWord32Shl) ||
14831cb0ef41Sopenharmony_ci         (node->opcode() == IrOpcode::kWord32Shr) ||
14841cb0ef41Sopenharmony_ci         (node->opcode() == IrOpcode::kWord32Sar));
14851cb0ef41Sopenharmony_ci  if (machine()->Word32ShiftIsSafe()) {
14861cb0ef41Sopenharmony_ci    // Remove the explicit 'and' with 0x1F if the shift provided by the machine
14871cb0ef41Sopenharmony_ci    // instruction matches that required by JavaScript.
14881cb0ef41Sopenharmony_ci    Int32BinopMatcher m(node);
14891cb0ef41Sopenharmony_ci    if (m.right().IsWord32And()) {
14901cb0ef41Sopenharmony_ci      Int32BinopMatcher mright(m.right().node());
14911cb0ef41Sopenharmony_ci      if (mright.right().Is(0x1F)) {
14921cb0ef41Sopenharmony_ci        node->ReplaceInput(1, mright.left().node());
14931cb0ef41Sopenharmony_ci        return Changed(node);
14941cb0ef41Sopenharmony_ci      }
14951cb0ef41Sopenharmony_ci    }
14961cb0ef41Sopenharmony_ci  }
14971cb0ef41Sopenharmony_ci  return NoChange();
14981cb0ef41Sopenharmony_ci}
14991cb0ef41Sopenharmony_ci
15001cb0ef41Sopenharmony_ciReduction MachineOperatorReducer::ReduceWord32Shl(Node* node) {
15011cb0ef41Sopenharmony_ci  DCHECK_EQ(IrOpcode::kWord32Shl, node->opcode());
15021cb0ef41Sopenharmony_ci  Int32BinopMatcher m(node);
15031cb0ef41Sopenharmony_ci  if (m.right().Is(0)) return Replace(m.left().node());  // x << 0 => x
15041cb0ef41Sopenharmony_ci  if (m.IsFoldable()) {  // K << K => K  (K stands for arbitrary constants)
15051cb0ef41Sopenharmony_ci    return ReplaceInt32(base::ShlWithWraparound(m.left().ResolvedValue(),
15061cb0ef41Sopenharmony_ci                                                m.right().ResolvedValue()));
15071cb0ef41Sopenharmony_ci  }
15081cb0ef41Sopenharmony_ci  if (m.right().IsInRange(1, 31)) {
15091cb0ef41Sopenharmony_ci    if (m.left().IsWord32Sar() || m.left().IsWord32Shr()) {
15101cb0ef41Sopenharmony_ci      Int32BinopMatcher mleft(m.left().node());
15111cb0ef41Sopenharmony_ci
15121cb0ef41Sopenharmony_ci      // If x >> K only shifted out zeros:
15131cb0ef41Sopenharmony_ci      // (x >> K) << L => x           if K == L
15141cb0ef41Sopenharmony_ci      // (x >> K) << L => x >> (K-L) if K > L
15151cb0ef41Sopenharmony_ci      // (x >> K) << L => x << (L-K)  if K < L
15161cb0ef41Sopenharmony_ci      // Since this is used for Smi untagging, we currently only need it for
15171cb0ef41Sopenharmony_ci      // signed shifts.
15181cb0ef41Sopenharmony_ci      if (mleft.op() == machine()->Word32SarShiftOutZeros() &&
15191cb0ef41Sopenharmony_ci          mleft.right().IsInRange(1, 31)) {
15201cb0ef41Sopenharmony_ci        Node* x = mleft.left().node();
15211cb0ef41Sopenharmony_ci        int k = mleft.right().ResolvedValue();
15221cb0ef41Sopenharmony_ci        int l = m.right().ResolvedValue();
15231cb0ef41Sopenharmony_ci        if (k == l) {
15241cb0ef41Sopenharmony_ci          return Replace(x);
15251cb0ef41Sopenharmony_ci        } else if (k > l) {
15261cb0ef41Sopenharmony_ci          node->ReplaceInput(0, x);
15271cb0ef41Sopenharmony_ci          node->ReplaceInput(1, Uint32Constant(k - l));
15281cb0ef41Sopenharmony_ci          NodeProperties::ChangeOp(node, machine()->Word32Sar());
15291cb0ef41Sopenharmony_ci          return Changed(node).FollowedBy(ReduceWord32Sar(node));
15301cb0ef41Sopenharmony_ci        } else {
15311cb0ef41Sopenharmony_ci          DCHECK(k < l);
15321cb0ef41Sopenharmony_ci          node->ReplaceInput(0, x);
15331cb0ef41Sopenharmony_ci          node->ReplaceInput(1, Uint32Constant(l - k));
15341cb0ef41Sopenharmony_ci          return Changed(node);
15351cb0ef41Sopenharmony_ci        }
15361cb0ef41Sopenharmony_ci      }
15371cb0ef41Sopenharmony_ci
15381cb0ef41Sopenharmony_ci      // (x >>> K) << K => x & ~(2^K - 1)
15391cb0ef41Sopenharmony_ci      // (x >> K) << K => x & ~(2^K - 1)
15401cb0ef41Sopenharmony_ci      if (mleft.right().Is(m.right().ResolvedValue())) {
15411cb0ef41Sopenharmony_ci        node->ReplaceInput(0, mleft.left().node());
15421cb0ef41Sopenharmony_ci        node->ReplaceInput(1,
15431cb0ef41Sopenharmony_ci                           Uint32Constant(std::numeric_limits<uint32_t>::max()
15441cb0ef41Sopenharmony_ci                                          << m.right().ResolvedValue()));
15451cb0ef41Sopenharmony_ci        NodeProperties::ChangeOp(node, machine()->Word32And());
15461cb0ef41Sopenharmony_ci        return Changed(node).FollowedBy(ReduceWord32And(node));
15471cb0ef41Sopenharmony_ci      }
15481cb0ef41Sopenharmony_ci    }
15491cb0ef41Sopenharmony_ci  }
15501cb0ef41Sopenharmony_ci  return ReduceWord32Shifts(node);
15511cb0ef41Sopenharmony_ci}
15521cb0ef41Sopenharmony_ci
15531cb0ef41Sopenharmony_ciReduction MachineOperatorReducer::ReduceWord64Shl(Node* node) {
15541cb0ef41Sopenharmony_ci  DCHECK_EQ(IrOpcode::kWord64Shl, node->opcode());
15551cb0ef41Sopenharmony_ci  Int64BinopMatcher m(node);
15561cb0ef41Sopenharmony_ci  if (m.right().Is(0)) return Replace(m.left().node());  // x << 0 => x
15571cb0ef41Sopenharmony_ci  if (m.IsFoldable()) {  // K << K => K  (K stands for arbitrary constants)
15581cb0ef41Sopenharmony_ci    return ReplaceInt64(base::ShlWithWraparound(m.left().ResolvedValue(),
15591cb0ef41Sopenharmony_ci                                                m.right().ResolvedValue()));
15601cb0ef41Sopenharmony_ci  }
15611cb0ef41Sopenharmony_ci  if (m.right().IsInRange(1, 63) &&
15621cb0ef41Sopenharmony_ci      (m.left().IsWord64Sar() || m.left().IsWord64Shr())) {
15631cb0ef41Sopenharmony_ci    Int64BinopMatcher mleft(m.left().node());
15641cb0ef41Sopenharmony_ci
15651cb0ef41Sopenharmony_ci    // If x >> K only shifted out zeros:
15661cb0ef41Sopenharmony_ci    // (x >> K) << L => x           if K == L
15671cb0ef41Sopenharmony_ci    // (x >> K) << L => x >> (K-L) if K > L
15681cb0ef41Sopenharmony_ci    // (x >> K) << L => x << (L-K)  if K < L
15691cb0ef41Sopenharmony_ci    // Since this is used for Smi untagging, we currently only need it for
15701cb0ef41Sopenharmony_ci    // signed shifts.
15711cb0ef41Sopenharmony_ci    if (mleft.op() == machine()->Word64SarShiftOutZeros() &&
15721cb0ef41Sopenharmony_ci        mleft.right().IsInRange(1, 63)) {
15731cb0ef41Sopenharmony_ci      Node* x = mleft.left().node();
15741cb0ef41Sopenharmony_ci      int64_t k = mleft.right().ResolvedValue();
15751cb0ef41Sopenharmony_ci      int64_t l = m.right().ResolvedValue();
15761cb0ef41Sopenharmony_ci      if (k == l) {
15771cb0ef41Sopenharmony_ci        return Replace(x);
15781cb0ef41Sopenharmony_ci      } else if (k > l) {
15791cb0ef41Sopenharmony_ci        node->ReplaceInput(0, x);
15801cb0ef41Sopenharmony_ci        node->ReplaceInput(1, Uint64Constant(k - l));
15811cb0ef41Sopenharmony_ci        NodeProperties::ChangeOp(node, machine()->Word64Sar());
15821cb0ef41Sopenharmony_ci        return Changed(node).FollowedBy(ReduceWord64Sar(node));
15831cb0ef41Sopenharmony_ci      } else {
15841cb0ef41Sopenharmony_ci        DCHECK(k < l);
15851cb0ef41Sopenharmony_ci        node->ReplaceInput(0, x);
15861cb0ef41Sopenharmony_ci        node->ReplaceInput(1, Uint64Constant(l - k));
15871cb0ef41Sopenharmony_ci        return Changed(node);
15881cb0ef41Sopenharmony_ci      }
15891cb0ef41Sopenharmony_ci    }
15901cb0ef41Sopenharmony_ci
15911cb0ef41Sopenharmony_ci    // (x >>> K) << K => x & ~(2^K - 1)
15921cb0ef41Sopenharmony_ci    // (x >> K) << K => x & ~(2^K - 1)
15931cb0ef41Sopenharmony_ci    if (mleft.right().Is(m.right().ResolvedValue())) {
15941cb0ef41Sopenharmony_ci      node->ReplaceInput(0, mleft.left().node());
15951cb0ef41Sopenharmony_ci      node->ReplaceInput(1, Uint64Constant(std::numeric_limits<uint64_t>::max()
15961cb0ef41Sopenharmony_ci                                           << m.right().ResolvedValue()));
15971cb0ef41Sopenharmony_ci      NodeProperties::ChangeOp(node, machine()->Word64And());
15981cb0ef41Sopenharmony_ci      return Changed(node).FollowedBy(ReduceWord64And(node));
15991cb0ef41Sopenharmony_ci    }
16001cb0ef41Sopenharmony_ci  }
16011cb0ef41Sopenharmony_ci  return NoChange();
16021cb0ef41Sopenharmony_ci}
16031cb0ef41Sopenharmony_ci
16041cb0ef41Sopenharmony_ciReduction MachineOperatorReducer::ReduceWord32Shr(Node* node) {
16051cb0ef41Sopenharmony_ci  Uint32BinopMatcher m(node);
16061cb0ef41Sopenharmony_ci  if (m.right().Is(0)) return Replace(m.left().node());  // x >>> 0 => x
16071cb0ef41Sopenharmony_ci  if (m.IsFoldable()) {  // K >>> K => K  (K stands for arbitrary constants)
16081cb0ef41Sopenharmony_ci    return ReplaceInt32(m.left().ResolvedValue() >>
16091cb0ef41Sopenharmony_ci                        (m.right().ResolvedValue() & 31));
16101cb0ef41Sopenharmony_ci  }
16111cb0ef41Sopenharmony_ci  if (m.left().IsWord32And() && m.right().HasResolvedValue()) {
16121cb0ef41Sopenharmony_ci    Uint32BinopMatcher mleft(m.left().node());
16131cb0ef41Sopenharmony_ci    if (mleft.right().HasResolvedValue()) {
16141cb0ef41Sopenharmony_ci      uint32_t shift = m.right().ResolvedValue() & 31;
16151cb0ef41Sopenharmony_ci      uint32_t mask = mleft.right().ResolvedValue();
16161cb0ef41Sopenharmony_ci      if ((mask >> shift) == 0) {
16171cb0ef41Sopenharmony_ci        // (m >>> s) == 0 implies ((x & m) >>> s) == 0
16181cb0ef41Sopenharmony_ci        return ReplaceInt32(0);
16191cb0ef41Sopenharmony_ci      }
16201cb0ef41Sopenharmony_ci    }
16211cb0ef41Sopenharmony_ci  }
16221cb0ef41Sopenharmony_ci  return ReduceWord32Shifts(node);
16231cb0ef41Sopenharmony_ci}
16241cb0ef41Sopenharmony_ci
16251cb0ef41Sopenharmony_ciReduction MachineOperatorReducer::ReduceWord64Shr(Node* node) {
16261cb0ef41Sopenharmony_ci  DCHECK_EQ(IrOpcode::kWord64Shr, node->opcode());
16271cb0ef41Sopenharmony_ci  Uint64BinopMatcher m(node);
16281cb0ef41Sopenharmony_ci  if (m.right().Is(0)) return Replace(m.left().node());  // x >>> 0 => x
16291cb0ef41Sopenharmony_ci  if (m.IsFoldable()) {  // K >> K => K  (K stands for arbitrary constants)
16301cb0ef41Sopenharmony_ci    return ReplaceInt64(m.left().ResolvedValue() >>
16311cb0ef41Sopenharmony_ci                        (m.right().ResolvedValue() & 63));
16321cb0ef41Sopenharmony_ci  }
16331cb0ef41Sopenharmony_ci  return NoChange();
16341cb0ef41Sopenharmony_ci}
16351cb0ef41Sopenharmony_ci
16361cb0ef41Sopenharmony_ciReduction MachineOperatorReducer::ReduceWord32Sar(Node* node) {
16371cb0ef41Sopenharmony_ci  Int32BinopMatcher m(node);
16381cb0ef41Sopenharmony_ci  if (m.right().Is(0)) return Replace(m.left().node());  // x >> 0 => x
16391cb0ef41Sopenharmony_ci  if (m.IsFoldable()) {  // K >> K => K  (K stands for arbitrary constants)
16401cb0ef41Sopenharmony_ci    return ReplaceInt32(m.left().ResolvedValue() >>
16411cb0ef41Sopenharmony_ci                        (m.right().ResolvedValue() & 31));
16421cb0ef41Sopenharmony_ci  }
16431cb0ef41Sopenharmony_ci  if (m.left().IsWord32Shl()) {
16441cb0ef41Sopenharmony_ci    Int32BinopMatcher mleft(m.left().node());
16451cb0ef41Sopenharmony_ci    if (mleft.left().IsComparison()) {
16461cb0ef41Sopenharmony_ci      if (m.right().Is(31) && mleft.right().Is(31)) {
16471cb0ef41Sopenharmony_ci        // Comparison << 31 >> 31 => 0 - Comparison
16481cb0ef41Sopenharmony_ci        node->ReplaceInput(0, Int32Constant(0));
16491cb0ef41Sopenharmony_ci        node->ReplaceInput(1, mleft.left().node());
16501cb0ef41Sopenharmony_ci        NodeProperties::ChangeOp(node, machine()->Int32Sub());
16511cb0ef41Sopenharmony_ci        return Changed(node).FollowedBy(ReduceInt32Sub(node));
16521cb0ef41Sopenharmony_ci      }
16531cb0ef41Sopenharmony_ci    } else if (mleft.left().IsLoad()) {
16541cb0ef41Sopenharmony_ci      LoadRepresentation const rep =
16551cb0ef41Sopenharmony_ci          LoadRepresentationOf(mleft.left().node()->op());
16561cb0ef41Sopenharmony_ci      if (m.right().Is(24) && mleft.right().Is(24) &&
16571cb0ef41Sopenharmony_ci          rep == MachineType::Int8()) {
16581cb0ef41Sopenharmony_ci        // Load[kMachInt8] << 24 >> 24 => Load[kMachInt8]
16591cb0ef41Sopenharmony_ci        return Replace(mleft.left().node());
16601cb0ef41Sopenharmony_ci      }
16611cb0ef41Sopenharmony_ci      if (m.right().Is(16) && mleft.right().Is(16) &&
16621cb0ef41Sopenharmony_ci          rep == MachineType::Int16()) {
16631cb0ef41Sopenharmony_ci        // Load[kMachInt16] << 16 >> 16 => Load[kMachInt8]
16641cb0ef41Sopenharmony_ci        return Replace(mleft.left().node());
16651cb0ef41Sopenharmony_ci      }
16661cb0ef41Sopenharmony_ci    }
16671cb0ef41Sopenharmony_ci  }
16681cb0ef41Sopenharmony_ci  return ReduceWord32Shifts(node);
16691cb0ef41Sopenharmony_ci}
16701cb0ef41Sopenharmony_ci
16711cb0ef41Sopenharmony_ciReduction MachineOperatorReducer::ReduceWord64Sar(Node* node) {
16721cb0ef41Sopenharmony_ci  Int64BinopMatcher m(node);
16731cb0ef41Sopenharmony_ci  if (m.right().Is(0)) return Replace(m.left().node());  // x >> 0 => x
16741cb0ef41Sopenharmony_ci  if (m.IsFoldable()) {
16751cb0ef41Sopenharmony_ci    return ReplaceInt64(m.left().ResolvedValue() >>
16761cb0ef41Sopenharmony_ci                        (m.right().ResolvedValue() & 63));
16771cb0ef41Sopenharmony_ci  }
16781cb0ef41Sopenharmony_ci  return NoChange();
16791cb0ef41Sopenharmony_ci}
16801cb0ef41Sopenharmony_ci
16811cb0ef41Sopenharmony_citemplate <typename WordNAdapter>
16821cb0ef41Sopenharmony_ciReduction MachineOperatorReducer::ReduceWordNAnd(Node* node) {
16831cb0ef41Sopenharmony_ci  using A = WordNAdapter;
16841cb0ef41Sopenharmony_ci  A a(this);
16851cb0ef41Sopenharmony_ci
16861cb0ef41Sopenharmony_ci  typename A::IntNBinopMatcher m(node);
16871cb0ef41Sopenharmony_ci  if (m.right().Is(0)) return Replace(m.right().node());  // x & 0  => 0
16881cb0ef41Sopenharmony_ci  if (m.right().Is(-1)) return Replace(m.left().node());  // x & -1 => x
16891cb0ef41Sopenharmony_ci  if (m.left().IsComparison() && m.right().Is(1)) {       // CMP & 1 => CMP
16901cb0ef41Sopenharmony_ci    return Replace(m.left().node());
16911cb0ef41Sopenharmony_ci  }
16921cb0ef41Sopenharmony_ci  if (m.IsFoldable()) {  // K & K  => K  (K stands for arbitrary constants)
16931cb0ef41Sopenharmony_ci    return a.ReplaceIntN(m.left().ResolvedValue() & m.right().ResolvedValue());
16941cb0ef41Sopenharmony_ci  }
16951cb0ef41Sopenharmony_ci  if (m.LeftEqualsRight()) return Replace(m.left().node());  // x & x => x
16961cb0ef41Sopenharmony_ci  if (A::IsWordNAnd(m.left()) && m.right().HasResolvedValue()) {
16971cb0ef41Sopenharmony_ci    typename A::IntNBinopMatcher mleft(m.left().node());
16981cb0ef41Sopenharmony_ci    if (mleft.right().HasResolvedValue()) {  // (x & K) & K => x & K
16991cb0ef41Sopenharmony_ci      node->ReplaceInput(0, mleft.left().node());
17001cb0ef41Sopenharmony_ci      node->ReplaceInput(1, a.IntNConstant(m.right().ResolvedValue() &
17011cb0ef41Sopenharmony_ci                                           mleft.right().ResolvedValue()));
17021cb0ef41Sopenharmony_ci      return Changed(node).FollowedBy(a.ReduceWordNAnd(node));
17031cb0ef41Sopenharmony_ci    }
17041cb0ef41Sopenharmony_ci  }
17051cb0ef41Sopenharmony_ci  if (m.right().IsNegativePowerOf2()) {
17061cb0ef41Sopenharmony_ci    typename A::intN_t const mask = m.right().ResolvedValue();
17071cb0ef41Sopenharmony_ci    typename A::intN_t const neg_mask = base::NegateWithWraparound(mask);
17081cb0ef41Sopenharmony_ci    if (A::IsWordNShl(m.left())) {
17091cb0ef41Sopenharmony_ci      typename A::UintNBinopMatcher mleft(m.left().node());
17101cb0ef41Sopenharmony_ci      if (mleft.right().HasResolvedValue() &&
17111cb0ef41Sopenharmony_ci          (mleft.right().ResolvedValue() & (A::WORD_SIZE - 1)) >=
17121cb0ef41Sopenharmony_ci              base::bits::CountTrailingZeros(mask)) {
17131cb0ef41Sopenharmony_ci        // (x << L) & (-1 << K) => x << L iff L >= K
17141cb0ef41Sopenharmony_ci        return Replace(mleft.node());
17151cb0ef41Sopenharmony_ci      }
17161cb0ef41Sopenharmony_ci    } else if (A::IsIntNAdd(m.left())) {
17171cb0ef41Sopenharmony_ci      typename A::IntNBinopMatcher mleft(m.left().node());
17181cb0ef41Sopenharmony_ci      if (mleft.right().HasResolvedValue() &&
17191cb0ef41Sopenharmony_ci          (mleft.right().ResolvedValue() & mask) ==
17201cb0ef41Sopenharmony_ci              mleft.right().ResolvedValue()) {
17211cb0ef41Sopenharmony_ci        // (x + (K << L)) & (-1 << L) => (x & (-1 << L)) + (K << L)
17221cb0ef41Sopenharmony_ci        node->ReplaceInput(0,
17231cb0ef41Sopenharmony_ci                           a.WordNAnd(mleft.left().node(), m.right().node()));
17241cb0ef41Sopenharmony_ci        node->ReplaceInput(1, mleft.right().node());
17251cb0ef41Sopenharmony_ci        NodeProperties::ChangeOp(node, a.IntNAdd(machine()));
17261cb0ef41Sopenharmony_ci        return Changed(node).FollowedBy(a.ReduceIntNAdd(node));
17271cb0ef41Sopenharmony_ci      }
17281cb0ef41Sopenharmony_ci      if (A::IsIntNMul(mleft.left())) {
17291cb0ef41Sopenharmony_ci        typename A::IntNBinopMatcher mleftleft(mleft.left().node());
17301cb0ef41Sopenharmony_ci        if (mleftleft.right().IsMultipleOf(neg_mask)) {
17311cb0ef41Sopenharmony_ci          // (y * (K << L) + x) & (-1 << L) => (x & (-1 << L)) + y * (K << L)
17321cb0ef41Sopenharmony_ci          node->ReplaceInput(
17331cb0ef41Sopenharmony_ci              0, a.WordNAnd(mleft.right().node(), m.right().node()));
17341cb0ef41Sopenharmony_ci          node->ReplaceInput(1, mleftleft.node());
17351cb0ef41Sopenharmony_ci          NodeProperties::ChangeOp(node, a.IntNAdd(machine()));
17361cb0ef41Sopenharmony_ci          return Changed(node).FollowedBy(a.ReduceIntNAdd(node));
17371cb0ef41Sopenharmony_ci        }
17381cb0ef41Sopenharmony_ci      }
17391cb0ef41Sopenharmony_ci      if (A::IsIntNMul(mleft.right())) {
17401cb0ef41Sopenharmony_ci        typename A::IntNBinopMatcher mleftright(mleft.right().node());
17411cb0ef41Sopenharmony_ci        if (mleftright.right().IsMultipleOf(neg_mask)) {
17421cb0ef41Sopenharmony_ci          // (x + y * (K << L)) & (-1 << L) => (x & (-1 << L)) + y * (K << L)
17431cb0ef41Sopenharmony_ci          node->ReplaceInput(0,
17441cb0ef41Sopenharmony_ci                             a.WordNAnd(mleft.left().node(), m.right().node()));
17451cb0ef41Sopenharmony_ci          node->ReplaceInput(1, mleftright.node());
17461cb0ef41Sopenharmony_ci          NodeProperties::ChangeOp(node, a.IntNAdd(machine()));
17471cb0ef41Sopenharmony_ci          return Changed(node).FollowedBy(a.ReduceIntNAdd(node));
17481cb0ef41Sopenharmony_ci        }
17491cb0ef41Sopenharmony_ci      }
17501cb0ef41Sopenharmony_ci      if (A::IsWordNShl(mleft.left())) {
17511cb0ef41Sopenharmony_ci        typename A::IntNBinopMatcher mleftleft(mleft.left().node());
17521cb0ef41Sopenharmony_ci        if (mleftleft.right().Is(base::bits::CountTrailingZeros(mask))) {
17531cb0ef41Sopenharmony_ci          // (y << L + x) & (-1 << L) => (x & (-1 << L)) + y << L
17541cb0ef41Sopenharmony_ci          node->ReplaceInput(
17551cb0ef41Sopenharmony_ci              0, a.WordNAnd(mleft.right().node(), m.right().node()));
17561cb0ef41Sopenharmony_ci          node->ReplaceInput(1, mleftleft.node());
17571cb0ef41Sopenharmony_ci          NodeProperties::ChangeOp(node, a.IntNAdd(machine()));
17581cb0ef41Sopenharmony_ci          return Changed(node).FollowedBy(a.ReduceIntNAdd(node));
17591cb0ef41Sopenharmony_ci        }
17601cb0ef41Sopenharmony_ci      }
17611cb0ef41Sopenharmony_ci      if (A::IsWordNShl(mleft.right())) {
17621cb0ef41Sopenharmony_ci        typename A::IntNBinopMatcher mleftright(mleft.right().node());
17631cb0ef41Sopenharmony_ci        if (mleftright.right().Is(base::bits::CountTrailingZeros(mask))) {
17641cb0ef41Sopenharmony_ci          // (x + y << L) & (-1 << L) => (x & (-1 << L)) + y << L
17651cb0ef41Sopenharmony_ci          node->ReplaceInput(0,
17661cb0ef41Sopenharmony_ci                             a.WordNAnd(mleft.left().node(), m.right().node()));
17671cb0ef41Sopenharmony_ci          node->ReplaceInput(1, mleftright.node());
17681cb0ef41Sopenharmony_ci          NodeProperties::ChangeOp(node, a.IntNAdd(machine()));
17691cb0ef41Sopenharmony_ci          return Changed(node).FollowedBy(a.ReduceIntNAdd(node));
17701cb0ef41Sopenharmony_ci        }
17711cb0ef41Sopenharmony_ci      }
17721cb0ef41Sopenharmony_ci    } else if (A::IsIntNMul(m.left())) {
17731cb0ef41Sopenharmony_ci      typename A::IntNBinopMatcher mleft(m.left().node());
17741cb0ef41Sopenharmony_ci      if (mleft.right().IsMultipleOf(neg_mask)) {
17751cb0ef41Sopenharmony_ci        // (x * (K << L)) & (-1 << L) => x * (K << L)
17761cb0ef41Sopenharmony_ci        return Replace(mleft.node());
17771cb0ef41Sopenharmony_ci      }
17781cb0ef41Sopenharmony_ci    }
17791cb0ef41Sopenharmony_ci  }
17801cb0ef41Sopenharmony_ci  return NoChange();
17811cb0ef41Sopenharmony_ci}
17821cb0ef41Sopenharmony_ci
17831cb0ef41Sopenharmony_cinamespace {
17841cb0ef41Sopenharmony_ci
17851cb0ef41Sopenharmony_ci// Represents an operation of the form `(source & mask) == masked_value`.
17861cb0ef41Sopenharmony_ci// where each bit set in masked_value also has to be set in mask.
17871cb0ef41Sopenharmony_cistruct BitfieldCheck {
17881cb0ef41Sopenharmony_ci  Node* const source;
17891cb0ef41Sopenharmony_ci  uint32_t const mask;
17901cb0ef41Sopenharmony_ci  uint32_t const masked_value;
17911cb0ef41Sopenharmony_ci  bool const truncate_from_64_bit;
17921cb0ef41Sopenharmony_ci
17931cb0ef41Sopenharmony_ci  BitfieldCheck(Node* source, uint32_t mask, uint32_t masked_value,
17941cb0ef41Sopenharmony_ci                bool truncate_from_64_bit)
17951cb0ef41Sopenharmony_ci      : source(source),
17961cb0ef41Sopenharmony_ci        mask(mask),
17971cb0ef41Sopenharmony_ci        masked_value(masked_value),
17981cb0ef41Sopenharmony_ci        truncate_from_64_bit(truncate_from_64_bit) {
17991cb0ef41Sopenharmony_ci    CHECK_EQ(masked_value & ~mask, 0);
18001cb0ef41Sopenharmony_ci  }
18011cb0ef41Sopenharmony_ci
18021cb0ef41Sopenharmony_ci  static base::Optional<BitfieldCheck> Detect(Node* node) {
18031cb0ef41Sopenharmony_ci    // There are two patterns to check for here:
18041cb0ef41Sopenharmony_ci    // 1. Single-bit checks: `(val >> shift) & 1`, where:
18051cb0ef41Sopenharmony_ci    //    - the shift may be omitted, and/or
18061cb0ef41Sopenharmony_ci    //    - the result may be truncated from 64 to 32
18071cb0ef41Sopenharmony_ci    // 2. Equality checks: `(val & mask) == expected`, where:
18081cb0ef41Sopenharmony_ci    //    - val may be truncated from 64 to 32 before masking (see
18091cb0ef41Sopenharmony_ci    //      ReduceWord32EqualForConstantRhs)
18101cb0ef41Sopenharmony_ci    if (node->opcode() == IrOpcode::kWord32Equal) {
18111cb0ef41Sopenharmony_ci      Uint32BinopMatcher eq(node);
18121cb0ef41Sopenharmony_ci      if (eq.left().IsWord32And()) {
18131cb0ef41Sopenharmony_ci        Uint32BinopMatcher mand(eq.left().node());
18141cb0ef41Sopenharmony_ci        if (mand.right().HasResolvedValue() && eq.right().HasResolvedValue()) {
18151cb0ef41Sopenharmony_ci          uint32_t mask = mand.right().ResolvedValue();
18161cb0ef41Sopenharmony_ci          uint32_t masked_value = eq.right().ResolvedValue();
18171cb0ef41Sopenharmony_ci          if ((masked_value & ~mask) != 0) return {};
18181cb0ef41Sopenharmony_ci          if (mand.left().IsTruncateInt64ToInt32()) {
18191cb0ef41Sopenharmony_ci            return BitfieldCheck(
18201cb0ef41Sopenharmony_ci                NodeProperties::GetValueInput(mand.left().node(), 0), mask,
18211cb0ef41Sopenharmony_ci                masked_value, true);
18221cb0ef41Sopenharmony_ci          } else {
18231cb0ef41Sopenharmony_ci            return BitfieldCheck(mand.left().node(), mask, masked_value, false);
18241cb0ef41Sopenharmony_ci          }
18251cb0ef41Sopenharmony_ci        }
18261cb0ef41Sopenharmony_ci      }
18271cb0ef41Sopenharmony_ci    } else {
18281cb0ef41Sopenharmony_ci      if (node->opcode() == IrOpcode::kTruncateInt64ToInt32) {
18291cb0ef41Sopenharmony_ci        return TryDetectShiftAndMaskOneBit<Word64Adapter>(
18301cb0ef41Sopenharmony_ci            NodeProperties::GetValueInput(node, 0));
18311cb0ef41Sopenharmony_ci      } else {
18321cb0ef41Sopenharmony_ci        return TryDetectShiftAndMaskOneBit<Word32Adapter>(node);
18331cb0ef41Sopenharmony_ci      }
18341cb0ef41Sopenharmony_ci    }
18351cb0ef41Sopenharmony_ci    return {};
18361cb0ef41Sopenharmony_ci  }
18371cb0ef41Sopenharmony_ci
18381cb0ef41Sopenharmony_ci  base::Optional<BitfieldCheck> TryCombine(const BitfieldCheck& other) {
18391cb0ef41Sopenharmony_ci    if (source != other.source ||
18401cb0ef41Sopenharmony_ci        truncate_from_64_bit != other.truncate_from_64_bit)
18411cb0ef41Sopenharmony_ci      return {};
18421cb0ef41Sopenharmony_ci    uint32_t overlapping_bits = mask & other.mask;
18431cb0ef41Sopenharmony_ci    // It would be kind of strange to have any overlapping bits, but they can be
18441cb0ef41Sopenharmony_ci    // allowed as long as they don't require opposite values in the same
18451cb0ef41Sopenharmony_ci    // positions.
18461cb0ef41Sopenharmony_ci    if ((masked_value & overlapping_bits) !=
18471cb0ef41Sopenharmony_ci        (other.masked_value & overlapping_bits))
18481cb0ef41Sopenharmony_ci      return {};
18491cb0ef41Sopenharmony_ci    return BitfieldCheck{source, mask | other.mask,
18501cb0ef41Sopenharmony_ci                         masked_value | other.masked_value,
18511cb0ef41Sopenharmony_ci                         truncate_from_64_bit};
18521cb0ef41Sopenharmony_ci  }
18531cb0ef41Sopenharmony_ci
18541cb0ef41Sopenharmony_ci private:
18551cb0ef41Sopenharmony_ci  template <typename WordNAdapter>
18561cb0ef41Sopenharmony_ci  static base::Optional<BitfieldCheck> TryDetectShiftAndMaskOneBit(Node* node) {
18571cb0ef41Sopenharmony_ci    // Look for the pattern `(val >> shift) & 1`. The shift may be omitted.
18581cb0ef41Sopenharmony_ci    if (WordNAdapter::IsWordNAnd(NodeMatcher(node))) {
18591cb0ef41Sopenharmony_ci      typename WordNAdapter::IntNBinopMatcher mand(node);
18601cb0ef41Sopenharmony_ci      if (mand.right().HasResolvedValue() &&
18611cb0ef41Sopenharmony_ci          mand.right().ResolvedValue() == 1) {
18621cb0ef41Sopenharmony_ci        if (WordNAdapter::IsWordNShr(mand.left()) ||
18631cb0ef41Sopenharmony_ci            WordNAdapter::IsWordNSar(mand.left())) {
18641cb0ef41Sopenharmony_ci          typename WordNAdapter::UintNBinopMatcher shift(mand.left().node());
18651cb0ef41Sopenharmony_ci          if (shift.right().HasResolvedValue() &&
18661cb0ef41Sopenharmony_ci              shift.right().ResolvedValue() < 32u) {
18671cb0ef41Sopenharmony_ci            uint32_t mask = 1 << shift.right().ResolvedValue();
18681cb0ef41Sopenharmony_ci            return BitfieldCheck{shift.left().node(), mask, mask,
18691cb0ef41Sopenharmony_ci                                 WordNAdapter::WORD_SIZE == 64};
18701cb0ef41Sopenharmony_ci          }
18711cb0ef41Sopenharmony_ci        }
18721cb0ef41Sopenharmony_ci        return BitfieldCheck{mand.left().node(), 1, 1,
18731cb0ef41Sopenharmony_ci                             WordNAdapter::WORD_SIZE == 64};
18741cb0ef41Sopenharmony_ci      }
18751cb0ef41Sopenharmony_ci    }
18761cb0ef41Sopenharmony_ci    return {};
18771cb0ef41Sopenharmony_ci  }
18781cb0ef41Sopenharmony_ci};
18791cb0ef41Sopenharmony_ci
18801cb0ef41Sopenharmony_ci}  // namespace
18811cb0ef41Sopenharmony_ci
18821cb0ef41Sopenharmony_ciReduction MachineOperatorReducer::ReduceWord32And(Node* node) {
18831cb0ef41Sopenharmony_ci  DCHECK_EQ(IrOpcode::kWord32And, node->opcode());
18841cb0ef41Sopenharmony_ci  Reduction reduction = ReduceWordNAnd<Word32Adapter>(node);
18851cb0ef41Sopenharmony_ci  if (reduction.Changed()) {
18861cb0ef41Sopenharmony_ci    return reduction;
18871cb0ef41Sopenharmony_ci  }
18881cb0ef41Sopenharmony_ci
18891cb0ef41Sopenharmony_ci  // Attempt to detect multiple bitfield checks from the same bitfield struct
18901cb0ef41Sopenharmony_ci  // and fold them into a single check.
18911cb0ef41Sopenharmony_ci  Int32BinopMatcher m(node);
18921cb0ef41Sopenharmony_ci  if (auto right_bitfield = BitfieldCheck::Detect(m.right().node())) {
18931cb0ef41Sopenharmony_ci    if (auto left_bitfield = BitfieldCheck::Detect(m.left().node())) {
18941cb0ef41Sopenharmony_ci      if (auto combined_bitfield = left_bitfield->TryCombine(*right_bitfield)) {
18951cb0ef41Sopenharmony_ci        Node* source = combined_bitfield->source;
18961cb0ef41Sopenharmony_ci        if (combined_bitfield->truncate_from_64_bit) {
18971cb0ef41Sopenharmony_ci          source = TruncateInt64ToInt32(source);
18981cb0ef41Sopenharmony_ci        }
18991cb0ef41Sopenharmony_ci        node->ReplaceInput(0, Word32And(source, combined_bitfield->mask));
19001cb0ef41Sopenharmony_ci        node->ReplaceInput(1, Int32Constant(combined_bitfield->masked_value));
19011cb0ef41Sopenharmony_ci        NodeProperties::ChangeOp(node, machine()->Word32Equal());
19021cb0ef41Sopenharmony_ci        return Changed(node).FollowedBy(ReduceWord32Equal(node));
19031cb0ef41Sopenharmony_ci      }
19041cb0ef41Sopenharmony_ci    }
19051cb0ef41Sopenharmony_ci  }
19061cb0ef41Sopenharmony_ci
19071cb0ef41Sopenharmony_ci  return NoChange();
19081cb0ef41Sopenharmony_ci}
19091cb0ef41Sopenharmony_ci
19101cb0ef41Sopenharmony_ciReduction MachineOperatorReducer::ReduceWord64And(Node* node) {
19111cb0ef41Sopenharmony_ci  DCHECK_EQ(IrOpcode::kWord64And, node->opcode());
19121cb0ef41Sopenharmony_ci  return ReduceWordNAnd<Word64Adapter>(node);
19131cb0ef41Sopenharmony_ci}
19141cb0ef41Sopenharmony_ci
19151cb0ef41Sopenharmony_ciReduction MachineOperatorReducer::TryMatchWord32Ror(Node* node) {
19161cb0ef41Sopenharmony_ci  // Recognize rotation, we are matching and transforming as follows:
19171cb0ef41Sopenharmony_ci  //   x << y         |  x >>> (32 - y)    =>  x ror (32 - y)
19181cb0ef41Sopenharmony_ci  //   x << (32 - y)  |  x >>> y           =>  x ror y
19191cb0ef41Sopenharmony_ci  //   x << y         ^  x >>> (32 - y)    =>  x ror (32 - y)   if y & 31 != 0
19201cb0ef41Sopenharmony_ci  //   x << (32 - y)  ^  x >>> y           =>  x ror y          if y & 31 != 0
19211cb0ef41Sopenharmony_ci  // (As well as the commuted forms.)
19221cb0ef41Sopenharmony_ci  // Note the side condition for XOR: the optimization doesn't hold for
19231cb0ef41Sopenharmony_ci  // multiples of 32.
19241cb0ef41Sopenharmony_ci
19251cb0ef41Sopenharmony_ci  DCHECK(IrOpcode::kWord32Or == node->opcode() ||
19261cb0ef41Sopenharmony_ci         IrOpcode::kWord32Xor == node->opcode());
19271cb0ef41Sopenharmony_ci  Int32BinopMatcher m(node);
19281cb0ef41Sopenharmony_ci  Node* shl = nullptr;
19291cb0ef41Sopenharmony_ci  Node* shr = nullptr;
19301cb0ef41Sopenharmony_ci  if (m.left().IsWord32Shl() && m.right().IsWord32Shr()) {
19311cb0ef41Sopenharmony_ci    shl = m.left().node();
19321cb0ef41Sopenharmony_ci    shr = m.right().node();
19331cb0ef41Sopenharmony_ci  } else if (m.left().IsWord32Shr() && m.right().IsWord32Shl()) {
19341cb0ef41Sopenharmony_ci    shl = m.right().node();
19351cb0ef41Sopenharmony_ci    shr = m.left().node();
19361cb0ef41Sopenharmony_ci  } else {
19371cb0ef41Sopenharmony_ci    return NoChange();
19381cb0ef41Sopenharmony_ci  }
19391cb0ef41Sopenharmony_ci
19401cb0ef41Sopenharmony_ci  Int32BinopMatcher mshl(shl);
19411cb0ef41Sopenharmony_ci  Int32BinopMatcher mshr(shr);
19421cb0ef41Sopenharmony_ci  if (mshl.left().node() != mshr.left().node()) return NoChange();
19431cb0ef41Sopenharmony_ci
19441cb0ef41Sopenharmony_ci  if (mshl.right().HasResolvedValue() && mshr.right().HasResolvedValue()) {
19451cb0ef41Sopenharmony_ci    // Case where y is a constant.
19461cb0ef41Sopenharmony_ci    if (mshl.right().ResolvedValue() + mshr.right().ResolvedValue() != 32) {
19471cb0ef41Sopenharmony_ci      return NoChange();
19481cb0ef41Sopenharmony_ci    }
19491cb0ef41Sopenharmony_ci    if (node->opcode() == IrOpcode::kWord32Xor &&
19501cb0ef41Sopenharmony_ci        (mshl.right().ResolvedValue() & 31) == 0) {
19511cb0ef41Sopenharmony_ci      return NoChange();
19521cb0ef41Sopenharmony_ci    }
19531cb0ef41Sopenharmony_ci  } else {
19541cb0ef41Sopenharmony_ci    Node* sub = nullptr;
19551cb0ef41Sopenharmony_ci    Node* y = nullptr;
19561cb0ef41Sopenharmony_ci    if (mshl.right().IsInt32Sub()) {
19571cb0ef41Sopenharmony_ci      sub = mshl.right().node();
19581cb0ef41Sopenharmony_ci      y = mshr.right().node();
19591cb0ef41Sopenharmony_ci    } else if (mshr.right().IsInt32Sub()) {
19601cb0ef41Sopenharmony_ci      sub = mshr.right().node();
19611cb0ef41Sopenharmony_ci      y = mshl.right().node();
19621cb0ef41Sopenharmony_ci    } else {
19631cb0ef41Sopenharmony_ci      return NoChange();
19641cb0ef41Sopenharmony_ci    }
19651cb0ef41Sopenharmony_ci
19661cb0ef41Sopenharmony_ci    Int32BinopMatcher msub(sub);
19671cb0ef41Sopenharmony_ci    if (!msub.left().Is(32) || msub.right().node() != y) return NoChange();
19681cb0ef41Sopenharmony_ci    if (node->opcode() == IrOpcode::kWord32Xor) {
19691cb0ef41Sopenharmony_ci      return NoChange();  // Can't guarantee y & 31 != 0.
19701cb0ef41Sopenharmony_ci    }
19711cb0ef41Sopenharmony_ci  }
19721cb0ef41Sopenharmony_ci
19731cb0ef41Sopenharmony_ci  node->ReplaceInput(0, mshl.left().node());
19741cb0ef41Sopenharmony_ci  node->ReplaceInput(1, mshr.right().node());
19751cb0ef41Sopenharmony_ci  NodeProperties::ChangeOp(node, machine()->Word32Ror());
19761cb0ef41Sopenharmony_ci  return Changed(node);
19771cb0ef41Sopenharmony_ci}
19781cb0ef41Sopenharmony_ci
19791cb0ef41Sopenharmony_citemplate <typename WordNAdapter>
19801cb0ef41Sopenharmony_ciReduction MachineOperatorReducer::ReduceWordNOr(Node* node) {
19811cb0ef41Sopenharmony_ci  using A = WordNAdapter;
19821cb0ef41Sopenharmony_ci  A a(this);
19831cb0ef41Sopenharmony_ci
19841cb0ef41Sopenharmony_ci  typename A::IntNBinopMatcher m(node);
19851cb0ef41Sopenharmony_ci  if (m.right().Is(0)) return Replace(m.left().node());    // x | 0  => x
19861cb0ef41Sopenharmony_ci  if (m.right().Is(-1)) return Replace(m.right().node());  // x | -1 => -1
19871cb0ef41Sopenharmony_ci  if (m.IsFoldable()) {  // K | K  => K  (K stands for arbitrary constants)
19881cb0ef41Sopenharmony_ci    return a.ReplaceIntN(m.left().ResolvedValue() | m.right().ResolvedValue());
19891cb0ef41Sopenharmony_ci  }
19901cb0ef41Sopenharmony_ci  if (m.LeftEqualsRight()) return Replace(m.left().node());  // x | x => x
19911cb0ef41Sopenharmony_ci
19921cb0ef41Sopenharmony_ci  // (x & K1) | K2 => x | K2 if K2 has ones for every zero bit in K1.
19931cb0ef41Sopenharmony_ci  // This case can be constructed by UpdateWord and UpdateWord32 in CSA.
19941cb0ef41Sopenharmony_ci  if (m.right().HasResolvedValue()) {
19951cb0ef41Sopenharmony_ci    if (A::IsWordNAnd(m.left())) {
19961cb0ef41Sopenharmony_ci      typename A::IntNBinopMatcher mand(m.left().node());
19971cb0ef41Sopenharmony_ci      if (mand.right().HasResolvedValue()) {
19981cb0ef41Sopenharmony_ci        if ((m.right().ResolvedValue() | mand.right().ResolvedValue()) == -1) {
19991cb0ef41Sopenharmony_ci          node->ReplaceInput(0, mand.left().node());
20001cb0ef41Sopenharmony_ci          return Changed(node);
20011cb0ef41Sopenharmony_ci        }
20021cb0ef41Sopenharmony_ci      }
20031cb0ef41Sopenharmony_ci    }
20041cb0ef41Sopenharmony_ci  }
20051cb0ef41Sopenharmony_ci
20061cb0ef41Sopenharmony_ci  return a.TryMatchWordNRor(node);
20071cb0ef41Sopenharmony_ci}
20081cb0ef41Sopenharmony_ci
20091cb0ef41Sopenharmony_ciReduction MachineOperatorReducer::ReduceWord32Or(Node* node) {
20101cb0ef41Sopenharmony_ci  DCHECK_EQ(IrOpcode::kWord32Or, node->opcode());
20111cb0ef41Sopenharmony_ci  return ReduceWordNOr<Word32Adapter>(node);
20121cb0ef41Sopenharmony_ci}
20131cb0ef41Sopenharmony_ci
20141cb0ef41Sopenharmony_ciReduction MachineOperatorReducer::ReduceWord64Or(Node* node) {
20151cb0ef41Sopenharmony_ci  DCHECK_EQ(IrOpcode::kWord64Or, node->opcode());
20161cb0ef41Sopenharmony_ci  return ReduceWordNOr<Word64Adapter>(node);
20171cb0ef41Sopenharmony_ci}
20181cb0ef41Sopenharmony_ci
20191cb0ef41Sopenharmony_citemplate <typename WordNAdapter>
20201cb0ef41Sopenharmony_ciReduction MachineOperatorReducer::ReduceWordNXor(Node* node) {
20211cb0ef41Sopenharmony_ci  using A = WordNAdapter;
20221cb0ef41Sopenharmony_ci  A a(this);
20231cb0ef41Sopenharmony_ci
20241cb0ef41Sopenharmony_ci  typename A::IntNBinopMatcher m(node);
20251cb0ef41Sopenharmony_ci  if (m.right().Is(0)) return Replace(m.left().node());  // x ^ 0 => x
20261cb0ef41Sopenharmony_ci  if (m.IsFoldable()) {  // K ^ K => K  (K stands for arbitrary constants)
20271cb0ef41Sopenharmony_ci    return a.ReplaceIntN(m.left().ResolvedValue() ^ m.right().ResolvedValue());
20281cb0ef41Sopenharmony_ci  }
20291cb0ef41Sopenharmony_ci  if (m.LeftEqualsRight()) return ReplaceInt32(0);  // x ^ x => 0
20301cb0ef41Sopenharmony_ci  if (A::IsWordNXor(m.left()) && m.right().Is(-1)) {
20311cb0ef41Sopenharmony_ci    typename A::IntNBinopMatcher mleft(m.left().node());
20321cb0ef41Sopenharmony_ci    if (mleft.right().Is(-1)) {  // (x ^ -1) ^ -1 => x
20331cb0ef41Sopenharmony_ci      return Replace(mleft.left().node());
20341cb0ef41Sopenharmony_ci    }
20351cb0ef41Sopenharmony_ci  }
20361cb0ef41Sopenharmony_ci
20371cb0ef41Sopenharmony_ci  return a.TryMatchWordNRor(node);
20381cb0ef41Sopenharmony_ci}
20391cb0ef41Sopenharmony_ci
20401cb0ef41Sopenharmony_ciReduction MachineOperatorReducer::ReduceWord32Xor(Node* node) {
20411cb0ef41Sopenharmony_ci  DCHECK_EQ(IrOpcode::kWord32Xor, node->opcode());
20421cb0ef41Sopenharmony_ci  Int32BinopMatcher m(node);
20431cb0ef41Sopenharmony_ci  if (m.right().IsWord32Equal() && m.left().Is(1)) {
20441cb0ef41Sopenharmony_ci    return Replace(Word32Equal(m.right().node(), Int32Constant(0)));
20451cb0ef41Sopenharmony_ci  }
20461cb0ef41Sopenharmony_ci  return ReduceWordNXor<Word32Adapter>(node);
20471cb0ef41Sopenharmony_ci}
20481cb0ef41Sopenharmony_ci
20491cb0ef41Sopenharmony_ciReduction MachineOperatorReducer::ReduceWord64Xor(Node* node) {
20501cb0ef41Sopenharmony_ci  DCHECK_EQ(IrOpcode::kWord64Xor, node->opcode());
20511cb0ef41Sopenharmony_ci  return ReduceWordNXor<Word64Adapter>(node);
20521cb0ef41Sopenharmony_ci}
20531cb0ef41Sopenharmony_ci
20541cb0ef41Sopenharmony_ciReduction MachineOperatorReducer::ReduceWord32Equal(Node* node) {
20551cb0ef41Sopenharmony_ci  Int32BinopMatcher m(node);
20561cb0ef41Sopenharmony_ci  if (m.IsFoldable()) {  // K == K => K  (K stands for arbitrary constants)
20571cb0ef41Sopenharmony_ci    return ReplaceBool(m.left().ResolvedValue() == m.right().ResolvedValue());
20581cb0ef41Sopenharmony_ci  }
20591cb0ef41Sopenharmony_ci  if (m.left().IsInt32Sub() && m.right().Is(0)) {  // x - y == 0 => x == y
20601cb0ef41Sopenharmony_ci    Int32BinopMatcher msub(m.left().node());
20611cb0ef41Sopenharmony_ci    node->ReplaceInput(0, msub.left().node());
20621cb0ef41Sopenharmony_ci    node->ReplaceInput(1, msub.right().node());
20631cb0ef41Sopenharmony_ci    return Changed(node);
20641cb0ef41Sopenharmony_ci  }
20651cb0ef41Sopenharmony_ci  // TODO(turbofan): fold HeapConstant, ExternalReference, pointer compares
20661cb0ef41Sopenharmony_ci  if (m.LeftEqualsRight()) return ReplaceBool(true);  // x == x => true
20671cb0ef41Sopenharmony_ci  if (m.right().HasResolvedValue()) {
20681cb0ef41Sopenharmony_ci    base::Optional<std::pair<Node*, uint32_t>> replacements;
20691cb0ef41Sopenharmony_ci    if (m.left().IsTruncateInt64ToInt32()) {
20701cb0ef41Sopenharmony_ci      replacements = ReduceWord32EqualForConstantRhs<Word64Adapter>(
20711cb0ef41Sopenharmony_ci          NodeProperties::GetValueInput(m.left().node(), 0),
20721cb0ef41Sopenharmony_ci          static_cast<uint32_t>(m.right().ResolvedValue()));
20731cb0ef41Sopenharmony_ci    } else {
20741cb0ef41Sopenharmony_ci      replacements = ReduceWord32EqualForConstantRhs<Word32Adapter>(
20751cb0ef41Sopenharmony_ci          m.left().node(), static_cast<uint32_t>(m.right().ResolvedValue()));
20761cb0ef41Sopenharmony_ci    }
20771cb0ef41Sopenharmony_ci    if (replacements) {
20781cb0ef41Sopenharmony_ci      node->ReplaceInput(0, replacements->first);
20791cb0ef41Sopenharmony_ci      node->ReplaceInput(1, Uint32Constant(replacements->second));
20801cb0ef41Sopenharmony_ci      return Changed(node);
20811cb0ef41Sopenharmony_ci    }
20821cb0ef41Sopenharmony_ci  }
20831cb0ef41Sopenharmony_ci  // This is a workaround for not having escape analysis for wasm
20841cb0ef41Sopenharmony_ci  // (machine-level) turbofan graphs.
20851cb0ef41Sopenharmony_ci  if (!ObjectsMayAlias(m.left().node(), m.right().node())) {
20861cb0ef41Sopenharmony_ci    return ReplaceBool(false);
20871cb0ef41Sopenharmony_ci  }
20881cb0ef41Sopenharmony_ci
20891cb0ef41Sopenharmony_ci  return NoChange();
20901cb0ef41Sopenharmony_ci}
20911cb0ef41Sopenharmony_ci
20921cb0ef41Sopenharmony_ciReduction MachineOperatorReducer::ReduceFloat64InsertLowWord32(Node* node) {
20931cb0ef41Sopenharmony_ci  DCHECK_EQ(IrOpcode::kFloat64InsertLowWord32, node->opcode());
20941cb0ef41Sopenharmony_ci  Float64Matcher mlhs(node->InputAt(0));
20951cb0ef41Sopenharmony_ci  Uint32Matcher mrhs(node->InputAt(1));
20961cb0ef41Sopenharmony_ci  if (mlhs.HasResolvedValue() && mrhs.HasResolvedValue()) {
20971cb0ef41Sopenharmony_ci    return ReplaceFloat64(
20981cb0ef41Sopenharmony_ci        bit_cast<double>((bit_cast<uint64_t>(mlhs.ResolvedValue()) &
20991cb0ef41Sopenharmony_ci                          uint64_t{0xFFFFFFFF00000000}) |
21001cb0ef41Sopenharmony_ci                         mrhs.ResolvedValue()));
21011cb0ef41Sopenharmony_ci  }
21021cb0ef41Sopenharmony_ci  return NoChange();
21031cb0ef41Sopenharmony_ci}
21041cb0ef41Sopenharmony_ci
21051cb0ef41Sopenharmony_ciReduction MachineOperatorReducer::ReduceFloat64InsertHighWord32(Node* node) {
21061cb0ef41Sopenharmony_ci  DCHECK_EQ(IrOpcode::kFloat64InsertHighWord32, node->opcode());
21071cb0ef41Sopenharmony_ci  Float64Matcher mlhs(node->InputAt(0));
21081cb0ef41Sopenharmony_ci  Uint32Matcher mrhs(node->InputAt(1));
21091cb0ef41Sopenharmony_ci  if (mlhs.HasResolvedValue() && mrhs.HasResolvedValue()) {
21101cb0ef41Sopenharmony_ci    return ReplaceFloat64(bit_cast<double>(
21111cb0ef41Sopenharmony_ci        (bit_cast<uint64_t>(mlhs.ResolvedValue()) & uint64_t{0xFFFFFFFF}) |
21121cb0ef41Sopenharmony_ci        (static_cast<uint64_t>(mrhs.ResolvedValue()) << 32)));
21131cb0ef41Sopenharmony_ci  }
21141cb0ef41Sopenharmony_ci  return NoChange();
21151cb0ef41Sopenharmony_ci}
21161cb0ef41Sopenharmony_ci
21171cb0ef41Sopenharmony_cinamespace {
21181cb0ef41Sopenharmony_ci
21191cb0ef41Sopenharmony_cibool IsFloat64RepresentableAsFloat32(const Float64Matcher& m) {
21201cb0ef41Sopenharmony_ci  if (m.HasResolvedValue()) {
21211cb0ef41Sopenharmony_ci    double v = m.ResolvedValue();
21221cb0ef41Sopenharmony_ci    return DoubleToFloat32(v) == v;
21231cb0ef41Sopenharmony_ci  }
21241cb0ef41Sopenharmony_ci  return false;
21251cb0ef41Sopenharmony_ci}
21261cb0ef41Sopenharmony_ci
21271cb0ef41Sopenharmony_ci}  // namespace
21281cb0ef41Sopenharmony_ci
21291cb0ef41Sopenharmony_ciReduction MachineOperatorReducer::ReduceFloat64Compare(Node* node) {
21301cb0ef41Sopenharmony_ci  DCHECK(IrOpcode::kFloat64Equal == node->opcode() ||
21311cb0ef41Sopenharmony_ci         IrOpcode::kFloat64LessThan == node->opcode() ||
21321cb0ef41Sopenharmony_ci         IrOpcode::kFloat64LessThanOrEqual == node->opcode());
21331cb0ef41Sopenharmony_ci  Float64BinopMatcher m(node);
21341cb0ef41Sopenharmony_ci  if (m.IsFoldable()) {
21351cb0ef41Sopenharmony_ci    switch (node->opcode()) {
21361cb0ef41Sopenharmony_ci      case IrOpcode::kFloat64Equal:
21371cb0ef41Sopenharmony_ci        return ReplaceBool(m.left().ResolvedValue() ==
21381cb0ef41Sopenharmony_ci                           m.right().ResolvedValue());
21391cb0ef41Sopenharmony_ci      case IrOpcode::kFloat64LessThan:
21401cb0ef41Sopenharmony_ci        return ReplaceBool(m.left().ResolvedValue() <
21411cb0ef41Sopenharmony_ci                           m.right().ResolvedValue());
21421cb0ef41Sopenharmony_ci      case IrOpcode::kFloat64LessThanOrEqual:
21431cb0ef41Sopenharmony_ci        return ReplaceBool(m.left().ResolvedValue() <=
21441cb0ef41Sopenharmony_ci                           m.right().ResolvedValue());
21451cb0ef41Sopenharmony_ci      default:
21461cb0ef41Sopenharmony_ci        UNREACHABLE();
21471cb0ef41Sopenharmony_ci    }
21481cb0ef41Sopenharmony_ci  } else if ((m.left().IsChangeFloat32ToFloat64() &&
21491cb0ef41Sopenharmony_ci              m.right().IsChangeFloat32ToFloat64()) ||
21501cb0ef41Sopenharmony_ci             (m.left().IsChangeFloat32ToFloat64() &&
21511cb0ef41Sopenharmony_ci              IsFloat64RepresentableAsFloat32(m.right())) ||
21521cb0ef41Sopenharmony_ci             (IsFloat64RepresentableAsFloat32(m.left()) &&
21531cb0ef41Sopenharmony_ci              m.right().IsChangeFloat32ToFloat64())) {
21541cb0ef41Sopenharmony_ci    // As all Float32 values have an exact representation in Float64, comparing
21551cb0ef41Sopenharmony_ci    // two Float64 values both converted from Float32 is equivalent to comparing
21561cb0ef41Sopenharmony_ci    // the original Float32s, so we can ignore the conversions. We can also
21571cb0ef41Sopenharmony_ci    // reduce comparisons of converted Float64 values against constants that
21581cb0ef41Sopenharmony_ci    // can be represented exactly as Float32.
21591cb0ef41Sopenharmony_ci    switch (node->opcode()) {
21601cb0ef41Sopenharmony_ci      case IrOpcode::kFloat64Equal:
21611cb0ef41Sopenharmony_ci        NodeProperties::ChangeOp(node, machine()->Float32Equal());
21621cb0ef41Sopenharmony_ci        break;
21631cb0ef41Sopenharmony_ci      case IrOpcode::kFloat64LessThan:
21641cb0ef41Sopenharmony_ci        NodeProperties::ChangeOp(node, machine()->Float32LessThan());
21651cb0ef41Sopenharmony_ci        break;
21661cb0ef41Sopenharmony_ci      case IrOpcode::kFloat64LessThanOrEqual:
21671cb0ef41Sopenharmony_ci        NodeProperties::ChangeOp(node, machine()->Float32LessThanOrEqual());
21681cb0ef41Sopenharmony_ci        break;
21691cb0ef41Sopenharmony_ci      default:
21701cb0ef41Sopenharmony_ci        UNREACHABLE();
21711cb0ef41Sopenharmony_ci    }
21721cb0ef41Sopenharmony_ci    node->ReplaceInput(
21731cb0ef41Sopenharmony_ci        0, m.left().HasResolvedValue()
21741cb0ef41Sopenharmony_ci               ? Float32Constant(static_cast<float>(m.left().ResolvedValue()))
21751cb0ef41Sopenharmony_ci               : m.left().InputAt(0));
21761cb0ef41Sopenharmony_ci    node->ReplaceInput(
21771cb0ef41Sopenharmony_ci        1, m.right().HasResolvedValue()
21781cb0ef41Sopenharmony_ci               ? Float32Constant(static_cast<float>(m.right().ResolvedValue()))
21791cb0ef41Sopenharmony_ci               : m.right().InputAt(0));
21801cb0ef41Sopenharmony_ci    return Changed(node);
21811cb0ef41Sopenharmony_ci  }
21821cb0ef41Sopenharmony_ci  return NoChange();
21831cb0ef41Sopenharmony_ci}
21841cb0ef41Sopenharmony_ci
21851cb0ef41Sopenharmony_ciReduction MachineOperatorReducer::ReduceFloat64RoundDown(Node* node) {
21861cb0ef41Sopenharmony_ci  DCHECK_EQ(IrOpcode::kFloat64RoundDown, node->opcode());
21871cb0ef41Sopenharmony_ci  Float64Matcher m(node->InputAt(0));
21881cb0ef41Sopenharmony_ci  if (m.HasResolvedValue()) {
21891cb0ef41Sopenharmony_ci    return ReplaceFloat64(std::floor(m.ResolvedValue()));
21901cb0ef41Sopenharmony_ci  }
21911cb0ef41Sopenharmony_ci  return NoChange();
21921cb0ef41Sopenharmony_ci}
21931cb0ef41Sopenharmony_ci
21941cb0ef41Sopenharmony_cinamespace {
21951cb0ef41Sopenharmony_ci
21961cb0ef41Sopenharmony_ci// Returns true if |node| is a constant whose value is 0.
21971cb0ef41Sopenharmony_cibool IsZero(Node* node) {
21981cb0ef41Sopenharmony_ci  switch (node->opcode()) {
21991cb0ef41Sopenharmony_ci#define CASE_IS_ZERO(opcode, matcher) \
22001cb0ef41Sopenharmony_ci  case IrOpcode::opcode: {            \
22011cb0ef41Sopenharmony_ci    matcher m(node);                  \
22021cb0ef41Sopenharmony_ci    return m.Is(0);                   \
22031cb0ef41Sopenharmony_ci  }
22041cb0ef41Sopenharmony_ci    CASE_IS_ZERO(kInt32Constant, Int32Matcher)
22051cb0ef41Sopenharmony_ci    CASE_IS_ZERO(kInt64Constant, Int64Matcher)
22061cb0ef41Sopenharmony_ci#undef CASE_IS_ZERO
22071cb0ef41Sopenharmony_ci    default:
22081cb0ef41Sopenharmony_ci      break;
22091cb0ef41Sopenharmony_ci  }
22101cb0ef41Sopenharmony_ci  return false;
22111cb0ef41Sopenharmony_ci}
22121cb0ef41Sopenharmony_ci
22131cb0ef41Sopenharmony_ci// If |node| is of the form "x == 0", then return "x" (in order to remove the
22141cb0ef41Sopenharmony_ci// "== 0" part).
22151cb0ef41Sopenharmony_cibase::Optional<Node*> TryGetInvertedCondition(Node* cond) {
22161cb0ef41Sopenharmony_ci  if (cond->opcode() == IrOpcode::kWord32Equal) {
22171cb0ef41Sopenharmony_ci    Int32BinopMatcher m(cond);
22181cb0ef41Sopenharmony_ci    if (IsZero(m.right().node())) {
22191cb0ef41Sopenharmony_ci      return m.left().node();
22201cb0ef41Sopenharmony_ci    }
22211cb0ef41Sopenharmony_ci  }
22221cb0ef41Sopenharmony_ci  return base::nullopt;
22231cb0ef41Sopenharmony_ci}
22241cb0ef41Sopenharmony_ci
22251cb0ef41Sopenharmony_cistruct SimplifiedCondition {
22261cb0ef41Sopenharmony_ci  Node* condition;
22271cb0ef41Sopenharmony_ci  bool is_inverted;
22281cb0ef41Sopenharmony_ci};
22291cb0ef41Sopenharmony_ci
22301cb0ef41Sopenharmony_ci// Tries to simplifies |cond| by removing all top-level "== 0". Everytime such a
22311cb0ef41Sopenharmony_ci// construction is removed, the meaning of the comparison is inverted. This is
22321cb0ef41Sopenharmony_ci// recorded by the variable |is_inverted| throughout this function, and returned
22331cb0ef41Sopenharmony_ci// at the end. If |is_inverted| is true at the end, the caller should invert the
22341cb0ef41Sopenharmony_ci// if/else branches following the comparison.
22351cb0ef41Sopenharmony_cibase::Optional<SimplifiedCondition> TrySimplifyCompareZero(Node* cond) {
22361cb0ef41Sopenharmony_ci  bool is_inverted = false;
22371cb0ef41Sopenharmony_ci  bool changed = false;
22381cb0ef41Sopenharmony_ci  base::Optional<Node*> new_cond;
22391cb0ef41Sopenharmony_ci  while ((new_cond = TryGetInvertedCondition(cond)).has_value()) {
22401cb0ef41Sopenharmony_ci    cond = *new_cond;
22411cb0ef41Sopenharmony_ci    is_inverted = !is_inverted;
22421cb0ef41Sopenharmony_ci    changed = true;
22431cb0ef41Sopenharmony_ci  }
22441cb0ef41Sopenharmony_ci  if (changed) {
22451cb0ef41Sopenharmony_ci    return SimplifiedCondition{cond, is_inverted};
22461cb0ef41Sopenharmony_ci  } else {
22471cb0ef41Sopenharmony_ci    return {};
22481cb0ef41Sopenharmony_ci  }
22491cb0ef41Sopenharmony_ci}
22501cb0ef41Sopenharmony_ci
22511cb0ef41Sopenharmony_ci}  // namespace
22521cb0ef41Sopenharmony_ci
22531cb0ef41Sopenharmony_civoid MachineOperatorReducer::SwapBranches(Node* node) {
22541cb0ef41Sopenharmony_ci  DCHECK_EQ(node->opcode(), IrOpcode::kBranch);
22551cb0ef41Sopenharmony_ci  for (Node* const use : node->uses()) {
22561cb0ef41Sopenharmony_ci    switch (use->opcode()) {
22571cb0ef41Sopenharmony_ci      case IrOpcode::kIfTrue:
22581cb0ef41Sopenharmony_ci        NodeProperties::ChangeOp(use, common()->IfFalse());
22591cb0ef41Sopenharmony_ci        break;
22601cb0ef41Sopenharmony_ci      case IrOpcode::kIfFalse:
22611cb0ef41Sopenharmony_ci        NodeProperties::ChangeOp(use, common()->IfTrue());
22621cb0ef41Sopenharmony_ci        break;
22631cb0ef41Sopenharmony_ci      default:
22641cb0ef41Sopenharmony_ci        UNREACHABLE();
22651cb0ef41Sopenharmony_ci    }
22661cb0ef41Sopenharmony_ci  }
22671cb0ef41Sopenharmony_ci  NodeProperties::ChangeOp(
22681cb0ef41Sopenharmony_ci      node, common()->Branch(NegateBranchHint(BranchHintOf(node->op()))));
22691cb0ef41Sopenharmony_ci}
22701cb0ef41Sopenharmony_ci
22711cb0ef41Sopenharmony_ci// If |node| is a branch, removes all top-level 32-bit "== 0" from |node|.
22721cb0ef41Sopenharmony_ciReduction MachineOperatorReducer::SimplifyBranch(Node* node) {
22731cb0ef41Sopenharmony_ci  Node* cond = node->InputAt(0);
22741cb0ef41Sopenharmony_ci  if (auto simplified = TrySimplifyCompareZero(cond)) {
22751cb0ef41Sopenharmony_ci    node->ReplaceInput(0, simplified->condition);
22761cb0ef41Sopenharmony_ci    if (simplified->is_inverted) {
22771cb0ef41Sopenharmony_ci      switch (node->opcode()) {
22781cb0ef41Sopenharmony_ci        case IrOpcode::kBranch:
22791cb0ef41Sopenharmony_ci          SwapBranches(node);
22801cb0ef41Sopenharmony_ci          break;
22811cb0ef41Sopenharmony_ci        case IrOpcode::kTrapIf:
22821cb0ef41Sopenharmony_ci          NodeProperties::ChangeOp(node,
22831cb0ef41Sopenharmony_ci                                   common()->TrapUnless(TrapIdOf(node->op())));
22841cb0ef41Sopenharmony_ci          break;
22851cb0ef41Sopenharmony_ci        case IrOpcode::kTrapUnless:
22861cb0ef41Sopenharmony_ci          NodeProperties::ChangeOp(node,
22871cb0ef41Sopenharmony_ci                                   common()->TrapIf(TrapIdOf(node->op())));
22881cb0ef41Sopenharmony_ci          break;
22891cb0ef41Sopenharmony_ci        case IrOpcode::kDeoptimizeIf: {
22901cb0ef41Sopenharmony_ci          DeoptimizeParameters p = DeoptimizeParametersOf(node->op());
22911cb0ef41Sopenharmony_ci          NodeProperties::ChangeOp(
22921cb0ef41Sopenharmony_ci              node, common()->DeoptimizeUnless(p.reason(), p.feedback()));
22931cb0ef41Sopenharmony_ci          break;
22941cb0ef41Sopenharmony_ci        }
22951cb0ef41Sopenharmony_ci        case IrOpcode::kDeoptimizeUnless: {
22961cb0ef41Sopenharmony_ci          DeoptimizeParameters p = DeoptimizeParametersOf(node->op());
22971cb0ef41Sopenharmony_ci          NodeProperties::ChangeOp(
22981cb0ef41Sopenharmony_ci              node, common()->DeoptimizeIf(p.reason(), p.feedback()));
22991cb0ef41Sopenharmony_ci          break;
23001cb0ef41Sopenharmony_ci        }
23011cb0ef41Sopenharmony_ci        default:
23021cb0ef41Sopenharmony_ci
23031cb0ef41Sopenharmony_ci          UNREACHABLE();
23041cb0ef41Sopenharmony_ci      }
23051cb0ef41Sopenharmony_ci    }
23061cb0ef41Sopenharmony_ci    return Changed(node);
23071cb0ef41Sopenharmony_ci  }
23081cb0ef41Sopenharmony_ci  return NoChange();
23091cb0ef41Sopenharmony_ci}
23101cb0ef41Sopenharmony_ci
23111cb0ef41Sopenharmony_ciReduction MachineOperatorReducer::ReduceConditional(Node* node) {
23121cb0ef41Sopenharmony_ci  DCHECK(node->opcode() == IrOpcode::kBranch ||
23131cb0ef41Sopenharmony_ci         node->opcode() == IrOpcode::kDeoptimizeIf ||
23141cb0ef41Sopenharmony_ci         node->opcode() == IrOpcode::kDeoptimizeUnless ||
23151cb0ef41Sopenharmony_ci         node->opcode() == IrOpcode::kTrapIf ||
23161cb0ef41Sopenharmony_ci         node->opcode() == IrOpcode::kTrapUnless);
23171cb0ef41Sopenharmony_ci  // This reducer only applies operator reductions to the branch condition.
23181cb0ef41Sopenharmony_ci  // Reductions involving control flow happen elsewhere. Non-zero inputs are
23191cb0ef41Sopenharmony_ci  // considered true in all conditional ops.
23201cb0ef41Sopenharmony_ci  NodeMatcher condition(NodeProperties::GetValueInput(node, 0));
23211cb0ef41Sopenharmony_ci  Reduction reduction = NoChange();
23221cb0ef41Sopenharmony_ci  if (condition.IsTruncateInt64ToInt32()) {
23231cb0ef41Sopenharmony_ci    if (auto replacement =
23241cb0ef41Sopenharmony_ci            ReduceConditionalN<Word64Adapter>(condition.node())) {
23251cb0ef41Sopenharmony_ci      NodeProperties::ReplaceValueInput(node, *replacement, 0);
23261cb0ef41Sopenharmony_ci      reduction = Changed(node);
23271cb0ef41Sopenharmony_ci    }
23281cb0ef41Sopenharmony_ci  } else if (auto replacement = ReduceConditionalN<Word32Adapter>(node)) {
23291cb0ef41Sopenharmony_ci    NodeProperties::ReplaceValueInput(node, *replacement, 0);
23301cb0ef41Sopenharmony_ci    reduction = Changed(node);
23311cb0ef41Sopenharmony_ci  }
23321cb0ef41Sopenharmony_ci  return reduction.FollowedBy(SimplifyBranch(node));
23331cb0ef41Sopenharmony_ci}
23341cb0ef41Sopenharmony_ci
23351cb0ef41Sopenharmony_citemplate <typename WordNAdapter>
23361cb0ef41Sopenharmony_cibase::Optional<Node*> MachineOperatorReducer::ReduceConditionalN(Node* node) {
23371cb0ef41Sopenharmony_ci  NodeMatcher condition(NodeProperties::GetValueInput(node, 0));
23381cb0ef41Sopenharmony_ci  // Branch conditions are 32-bit comparisons against zero, so they are the
23391cb0ef41Sopenharmony_ci  // opposite of a 32-bit `x == 0` node. To avoid repetition, we can reuse logic
23401cb0ef41Sopenharmony_ci  // for Word32Equal: if `x == 0` can reduce to `y == 0`, then branch(x) can
23411cb0ef41Sopenharmony_ci  // reduce to branch(y).
23421cb0ef41Sopenharmony_ci  auto replacements =
23431cb0ef41Sopenharmony_ci      ReduceWord32EqualForConstantRhs<WordNAdapter>(condition.node(), 0);
23441cb0ef41Sopenharmony_ci  if (replacements && replacements->second == 0) return replacements->first;
23451cb0ef41Sopenharmony_ci  return {};
23461cb0ef41Sopenharmony_ci}
23471cb0ef41Sopenharmony_ci
23481cb0ef41Sopenharmony_citemplate <typename WordNAdapter>
23491cb0ef41Sopenharmony_cibase::Optional<std::pair<Node*, uint32_t>>
23501cb0ef41Sopenharmony_ciMachineOperatorReducer::ReduceWord32EqualForConstantRhs(Node* lhs,
23511cb0ef41Sopenharmony_ci                                                        uint32_t rhs) {
23521cb0ef41Sopenharmony_ci  if (WordNAdapter::IsWordNAnd(NodeMatcher(lhs))) {
23531cb0ef41Sopenharmony_ci    typename WordNAdapter::UintNBinopMatcher mand(lhs);
23541cb0ef41Sopenharmony_ci    if ((WordNAdapter::IsWordNShr(mand.left()) ||
23551cb0ef41Sopenharmony_ci         WordNAdapter::IsWordNSar(mand.left())) &&
23561cb0ef41Sopenharmony_ci        mand.right().HasResolvedValue()) {
23571cb0ef41Sopenharmony_ci      typename WordNAdapter::UintNBinopMatcher mshift(mand.left().node());
23581cb0ef41Sopenharmony_ci      // ((x >> K1) & K2) == K3 => (x & (K2 << K1)) == (K3 << K1)
23591cb0ef41Sopenharmony_ci      if (mshift.right().HasResolvedValue()) {
23601cb0ef41Sopenharmony_ci        auto shift_bits = mshift.right().ResolvedValue();
23611cb0ef41Sopenharmony_ci        auto mask = mand.right().ResolvedValue();
23621cb0ef41Sopenharmony_ci        // Make sure that we won't shift data off the end, and that all of the
23631cb0ef41Sopenharmony_ci        // data ends up in the lower 32 bits for 64-bit mode.
23641cb0ef41Sopenharmony_ci        if (shift_bits <= base::bits::CountLeadingZeros(mask) &&
23651cb0ef41Sopenharmony_ci            shift_bits <= base::bits::CountLeadingZeros(rhs) &&
23661cb0ef41Sopenharmony_ci            mask << shift_bits <= std::numeric_limits<uint32_t>::max()) {
23671cb0ef41Sopenharmony_ci          Node* new_input = mshift.left().node();
23681cb0ef41Sopenharmony_ci          uint32_t new_mask = static_cast<uint32_t>(mask << shift_bits);
23691cb0ef41Sopenharmony_ci          uint32_t new_rhs = rhs << shift_bits;
23701cb0ef41Sopenharmony_ci          if (WordNAdapter::WORD_SIZE == 64) {
23711cb0ef41Sopenharmony_ci            // We can truncate before performing the And.
23721cb0ef41Sopenharmony_ci            new_input = TruncateInt64ToInt32(new_input);
23731cb0ef41Sopenharmony_ci          }
23741cb0ef41Sopenharmony_ci          return std::make_pair(Word32And(new_input, new_mask), new_rhs);
23751cb0ef41Sopenharmony_ci        }
23761cb0ef41Sopenharmony_ci      }
23771cb0ef41Sopenharmony_ci    }
23781cb0ef41Sopenharmony_ci  }
23791cb0ef41Sopenharmony_ci  // Replaces (x >> n) == k with x == k << n, with "k << n" being computed
23801cb0ef41Sopenharmony_ci  // here at compile time.
23811cb0ef41Sopenharmony_ci  if (lhs->op() == machine()->Word32SarShiftOutZeros() &&
23821cb0ef41Sopenharmony_ci      lhs->UseCount() == 1) {
23831cb0ef41Sopenharmony_ci    typename WordNAdapter::UintNBinopMatcher mshift(lhs);
23841cb0ef41Sopenharmony_ci    if (mshift.right().HasResolvedValue()) {
23851cb0ef41Sopenharmony_ci      int32_t shift = static_cast<int32_t>(mshift.right().ResolvedValue());
23861cb0ef41Sopenharmony_ci      if (CanRevertLeftShiftWithRightShift(rhs, shift)) {
23871cb0ef41Sopenharmony_ci        return std::make_pair(mshift.left().node(), rhs << shift);
23881cb0ef41Sopenharmony_ci      }
23891cb0ef41Sopenharmony_ci    }
23901cb0ef41Sopenharmony_ci  }
23911cb0ef41Sopenharmony_ci  return {};
23921cb0ef41Sopenharmony_ci}
23931cb0ef41Sopenharmony_ci
23941cb0ef41Sopenharmony_ciCommonOperatorBuilder* MachineOperatorReducer::common() const {
23951cb0ef41Sopenharmony_ci  return mcgraph()->common();
23961cb0ef41Sopenharmony_ci}
23971cb0ef41Sopenharmony_ci
23981cb0ef41Sopenharmony_ciMachineOperatorBuilder* MachineOperatorReducer::machine() const {
23991cb0ef41Sopenharmony_ci  return mcgraph()->machine();
24001cb0ef41Sopenharmony_ci}
24011cb0ef41Sopenharmony_ci
24021cb0ef41Sopenharmony_ciGraph* MachineOperatorReducer::graph() const { return mcgraph()->graph(); }
24031cb0ef41Sopenharmony_ci
24041cb0ef41Sopenharmony_ci}  // namespace compiler
24051cb0ef41Sopenharmony_ci}  // namespace internal
24061cb0ef41Sopenharmony_ci}  // namespace v8
2407