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