diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-10-12 14:27:29 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-10-13 09:35:20 +0000 |
commit | c30a6232df03e1efbd9f3b226777b07e087a1122 (patch) | |
tree | e992f45784689f373bcc38d1b79a239ebe17ee23 /chromium/v8/src/compiler/machine-operator-reducer.cc | |
parent | 7b5b123ac58f58ffde0f4f6e488bcd09aa4decd3 (diff) | |
download | qtwebengine-chromium-85-based.tar.gz |
BASELINE: Update Chromium to 85.0.4183.14085-based
Change-Id: Iaa42f4680837c57725b1344f108c0196741f6057
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/v8/src/compiler/machine-operator-reducer.cc')
-rw-r--r-- | chromium/v8/src/compiler/machine-operator-reducer.cc | 173 |
1 files changed, 143 insertions, 30 deletions
diff --git a/chromium/v8/src/compiler/machine-operator-reducer.cc b/chromium/v8/src/compiler/machine-operator-reducer.cc index 1b600291691..127c7681099 100644 --- a/chromium/v8/src/compiler/machine-operator-reducer.cc +++ b/chromium/v8/src/compiler/machine-operator-reducer.cc @@ -311,35 +311,7 @@ Reduction MachineOperatorReducer::Reduce(Node* node) { break; } case IrOpcode::kWord32Equal: { - Int32BinopMatcher m(node); - if (m.IsFoldable()) { // K == K => K - return ReplaceBool(m.left().Value() == m.right().Value()); - } - if (m.left().IsInt32Sub() && m.right().Is(0)) { // x - y == 0 => x == y - Int32BinopMatcher msub(m.left().node()); - node->ReplaceInput(0, msub.left().node()); - node->ReplaceInput(1, msub.right().node()); - return Changed(node); - } - // TODO(turbofan): fold HeapConstant, ExternalReference, pointer compares - if (m.LeftEqualsRight()) return ReplaceBool(true); // x == x => true - if (m.right().HasValue()) { - base::Optional<std::pair<Node*, uint32_t>> replacements; - if (m.left().IsTruncateInt64ToInt32()) { - replacements = ReduceWord32EqualForConstantRhs<Word64Adapter>( - NodeProperties::GetValueInput(m.left().node(), 0), - static_cast<uint32_t>(m.right().Value())); - } else { - replacements = ReduceWord32EqualForConstantRhs<Word32Adapter>( - m.left().node(), static_cast<uint32_t>(m.right().Value())); - } - if (replacements) { - node->ReplaceInput(0, replacements->first); - node->ReplaceInput(1, Uint32Constant(replacements->second)); - return Changed(node); - } - } - break; + return ReduceWord32Equal(node); } case IrOpcode::kWord64Equal: { Int64BinopMatcher m(node); @@ -1623,9 +1595,117 @@ Reduction MachineOperatorReducer::ReduceWordNAnd(Node* node) { return NoChange(); } +namespace { + +// Represents an operation of the form `(source & mask) == masked_value`. +struct BitfieldCheck { + Node* source; + uint32_t mask; + uint32_t masked_value; + bool truncate_from_64_bit; + + static base::Optional<BitfieldCheck> Detect(Node* node) { + // There are two patterns to check for here: + // 1. Single-bit checks: `(val >> shift) & 1`, where: + // - the shift may be omitted, and/or + // - the result may be truncated from 64 to 32 + // 2. Equality checks: `(val & mask) == expected`, where: + // - val may be truncated from 64 to 32 before masking (see + // ReduceWord32EqualForConstantRhs) + if (node->opcode() == IrOpcode::kWord32Equal) { + Uint32BinopMatcher eq(node); + if (eq.left().IsWord32And()) { + Uint32BinopMatcher mand(eq.left().node()); + if (mand.right().HasValue()) { + BitfieldCheck result{mand.left().node(), mand.right().Value(), + eq.right().Value(), false}; + if (mand.left().IsTruncateInt64ToInt32()) { + result.truncate_from_64_bit = true; + result.source = + NodeProperties::GetValueInput(mand.left().node(), 0); + } + return result; + } + } + } else { + if (node->opcode() == IrOpcode::kTruncateInt64ToInt32) { + return TryDetectShiftAndMaskOneBit<Word64Adapter>( + NodeProperties::GetValueInput(node, 0)); + } else { + return TryDetectShiftAndMaskOneBit<Word32Adapter>(node); + } + } + return {}; + } + + base::Optional<BitfieldCheck> TryCombine(const BitfieldCheck& other) { + if (source != other.source || + truncate_from_64_bit != other.truncate_from_64_bit) + return {}; + uint32_t overlapping_bits = mask & other.mask; + // It would be kind of strange to have any overlapping bits, but they can be + // allowed as long as they don't require opposite values in the same + // positions. + if ((masked_value & overlapping_bits) != + (other.masked_value & overlapping_bits)) + return {}; + return BitfieldCheck{source, mask | other.mask, + masked_value | other.masked_value, + truncate_from_64_bit}; + } + + private: + template <typename WordNAdapter> + static base::Optional<BitfieldCheck> TryDetectShiftAndMaskOneBit(Node* node) { + // Look for the pattern `(val >> shift) & 1`. The shift may be omitted. + if (WordNAdapter::IsWordNAnd(NodeMatcher(node))) { + typename WordNAdapter::IntNBinopMatcher mand(node); + if (mand.right().HasValue() && mand.right().Value() == 1) { + if (WordNAdapter::IsWordNShr(mand.left()) || + WordNAdapter::IsWordNSar(mand.left())) { + typename WordNAdapter::UintNBinopMatcher shift(mand.left().node()); + if (shift.right().HasValue() && shift.right().Value() < 32u) { + uint32_t mask = 1 << shift.right().Value(); + return BitfieldCheck{shift.left().node(), mask, mask, + WordNAdapter::WORD_SIZE == 64}; + } + } + return BitfieldCheck{mand.left().node(), 1, 1, + WordNAdapter::WORD_SIZE == 64}; + } + } + return {}; + } +}; + +} // namespace + Reduction MachineOperatorReducer::ReduceWord32And(Node* node) { DCHECK_EQ(IrOpcode::kWord32And, node->opcode()); - return ReduceWordNAnd<Word32Adapter>(node); + Reduction reduction = ReduceWordNAnd<Word32Adapter>(node); + if (reduction.Changed()) { + return reduction; + } + + // Attempt to detect multiple bitfield checks from the same bitfield struct + // and fold them into a single check. + Int32BinopMatcher m(node); + if (auto right_bitfield = BitfieldCheck::Detect(m.right().node())) { + if (auto left_bitfield = BitfieldCheck::Detect(m.left().node())) { + if (auto combined_bitfield = left_bitfield->TryCombine(*right_bitfield)) { + Node* source = combined_bitfield->source; + if (combined_bitfield->truncate_from_64_bit) { + source = TruncateInt64ToInt32(source); + } + node->ReplaceInput(0, Word32And(source, combined_bitfield->mask)); + node->ReplaceInput(1, Int32Constant(combined_bitfield->masked_value)); + NodeProperties::ChangeOp(node, machine()->Word32Equal()); + return Changed(node).FollowedBy(ReduceWord32Equal(node)); + } + } + } + + return NoChange(); } Reduction MachineOperatorReducer::ReduceWord64And(Node* node) { @@ -1756,6 +1836,39 @@ Reduction MachineOperatorReducer::ReduceWord64Xor(Node* node) { return ReduceWordNXor<Word64Adapter>(node); } +Reduction MachineOperatorReducer::ReduceWord32Equal(Node* node) { + Int32BinopMatcher m(node); + if (m.IsFoldable()) { // K == K => K + return ReplaceBool(m.left().Value() == m.right().Value()); + } + if (m.left().IsInt32Sub() && m.right().Is(0)) { // x - y == 0 => x == y + Int32BinopMatcher msub(m.left().node()); + node->ReplaceInput(0, msub.left().node()); + node->ReplaceInput(1, msub.right().node()); + return Changed(node); + } + // TODO(turbofan): fold HeapConstant, ExternalReference, pointer compares + if (m.LeftEqualsRight()) return ReplaceBool(true); // x == x => true + if (m.right().HasValue()) { + base::Optional<std::pair<Node*, uint32_t>> replacements; + if (m.left().IsTruncateInt64ToInt32()) { + replacements = ReduceWord32EqualForConstantRhs<Word64Adapter>( + NodeProperties::GetValueInput(m.left().node(), 0), + static_cast<uint32_t>(m.right().Value())); + } else { + replacements = ReduceWord32EqualForConstantRhs<Word32Adapter>( + m.left().node(), static_cast<uint32_t>(m.right().Value())); + } + if (replacements) { + node->ReplaceInput(0, replacements->first); + node->ReplaceInput(1, Uint32Constant(replacements->second)); + return Changed(node); + } + } + + return NoChange(); +} + Reduction MachineOperatorReducer::ReduceFloat64InsertLowWord32(Node* node) { DCHECK_EQ(IrOpcode::kFloat64InsertLowWord32, node->opcode()); Float64Matcher mlhs(node->InputAt(0)); |