Commit 9ec29a44 authored by Leszek Swirski's avatar Leszek Swirski Committed by V8 LUCI CQ

[maglev] Implement BranchIfInt32Compare

Add an implementation of BranchIfInt32Compare, which is emitted whenever
a compare op is immediately followed by a branch.

Bug: v8:7700
Change-Id: I2c56d9de199bac8de33b33201f8614aee8e9894e
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3647693Reviewed-by: 's avatarToon Verwaest <verwaest@chromium.org>
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
Cr-Commit-Position: refs/heads/main@{#80694}
parent 6a538088
...@@ -105,6 +105,15 @@ class V8_EXPORT_PRIVATE BytecodeArrayIterator { ...@@ -105,6 +105,15 @@ class V8_EXPORT_PRIVATE BytecodeArrayIterator {
return static_cast<int>(cursor_ - start_ - prefix_size_); return static_cast<int>(cursor_ - start_ - prefix_size_);
} }
int next_offset() const { return current_offset() + current_bytecode_size(); } int next_offset() const { return current_offset() + current_bytecode_size(); }
Bytecode next_bytecode() const {
uint8_t* next_cursor = cursor_ + current_bytecode_size_without_prefix();
if (next_cursor == end_) return Bytecode::kIllegal;
Bytecode next_bytecode = Bytecodes::FromByte(*next_cursor);
if (Bytecodes::IsPrefixScalingBytecode(next_bytecode)) {
next_bytecode = Bytecodes::FromByte(*(next_cursor + 1));
}
return next_bytecode;
}
OperandScale current_operand_scale() const { return operand_scale_; } OperandScale current_operand_scale() const { return operand_scale_; }
Handle<BytecodeArray> bytecode_array() const { return bytecode_array_; } Handle<BytecodeArray> bytecode_array() const { return bytecode_array_; }
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include "src/maglev/maglev-graph-builder.h" #include "src/maglev/maglev-graph-builder.h"
#include "src/base/v8-fallthrough.h"
#include "src/common/globals.h" #include "src/common/globals.h"
#include "src/compiler/compilation-dependencies.h" #include "src/compiler/compilation-dependencies.h"
#include "src/compiler/feedback-source.h" #include "src/compiler/feedback-source.h"
...@@ -12,6 +13,7 @@ ...@@ -12,6 +13,7 @@
#include "src/handles/maybe-handles-inl.h" #include "src/handles/maybe-handles-inl.h"
#include "src/ic/handler-configuration-inl.h" #include "src/ic/handler-configuration-inl.h"
#include "src/interpreter/bytecode-flags.h" #include "src/interpreter/bytecode-flags.h"
#include "src/interpreter/bytecodes.h"
#include "src/maglev/maglev-compilation-unit.h" #include "src/maglev/maglev-compilation-unit.h"
#include "src/maglev/maglev-interpreter-frame-state.h" #include "src/maglev/maglev-interpreter-frame-state.h"
#include "src/maglev/maglev-ir.h" #include "src/maglev/maglev-ir.h"
...@@ -414,13 +416,76 @@ void MaglevGraphBuilder::VisitBinarySmiOperation() { ...@@ -414,13 +416,76 @@ void MaglevGraphBuilder::VisitBinarySmiOperation() {
BuildGenericBinarySmiOperationNode<kOperation>(); BuildGenericBinarySmiOperationNode<kOperation>();
} }
bool MaglevGraphBuilder::TryBuildCompareOperationBranch(Operation operation,
ValueNode* left,
ValueNode* right) {
// Don't emit the shortcut branch if the next bytecode is a merge target.
if (IsOffsetAMergePoint(next_offset())) return false;
interpreter::Bytecode next_bytecode = iterator_.next_bytecode();
int true_offset;
int false_offset;
switch (next_bytecode) {
case interpreter::Bytecode::kJumpIfFalse:
case interpreter::Bytecode::kJumpIfFalseConstant:
case interpreter::Bytecode::kJumpIfToBooleanFalse:
case interpreter::Bytecode::kJumpIfToBooleanFalseConstant:
// This jump must kill the accumulator, otherwise we need to
// materialize the actual boolean value.
if (GetOutLiveness()->AccumulatorIsLive()) return false;
// Advance the iterator past the test to the jump, skipping
// emitting the test.
iterator_.Advance();
true_offset = next_offset();
false_offset = iterator_.GetJumpTargetOffset();
break;
case interpreter::Bytecode::kJumpIfTrue:
case interpreter::Bytecode::kJumpIfTrueConstant:
case interpreter::Bytecode::kJumpIfToBooleanTrue:
case interpreter::Bytecode::kJumpIfToBooleanTrueConstant:
// This jump must kill the accumulator, otherwise we need to
// materialize the actual boolean value.
if (GetOutLiveness()->AccumulatorIsLive()) return false;
// Advance the iterator past the test to the jump, skipping
// emitting the test.
iterator_.Advance();
true_offset = iterator_.GetJumpTargetOffset();
false_offset = next_offset();
break;
default:
return false;
}
BasicBlock* block = FinishBlock<BranchIfInt32Compare>(
next_offset(), {left, right}, operation, &jump_targets_[true_offset],
&jump_targets_[false_offset]);
MergeIntoFrameState(block, iterator_.GetJumpTargetOffset());
return true;
}
template <Operation kOperation> template <Operation kOperation>
void MaglevGraphBuilder::VisitCompareOperation() { void MaglevGraphBuilder::VisitCompareOperation() {
FeedbackNexus nexus = FeedbackNexusForOperand(1); FeedbackNexus nexus = FeedbackNexusForOperand(1);
switch (nexus.GetCompareOperationFeedback()) { switch (nexus.GetCompareOperationFeedback()) {
case CompareOperationHint::kSignedSmall: case CompareOperationHint::kSignedSmall:
if (BinaryOperationHasInt32FastPath<kOperation>()) { if (BinaryOperationHasInt32FastPath<kOperation>()) {
BuildInt32BinaryOperationNode<kOperation>(); ValueNode *left, *right;
if (IsRegisterEqualToAccumulator(0)) {
left = right = LoadRegisterInt32(0);
} else {
left = LoadRegisterInt32(0);
right = GetAccumulatorInt32();
}
if (TryBuildCompareOperationBranch(kOperation, left, right)) {
return;
}
SetAccumulator(
AddNewInt32BinaryOperationNode<kOperation>({left, right}));
return; return;
} }
break; break;
......
...@@ -584,6 +584,9 @@ class MaglevGraphBuilder { ...@@ -584,6 +584,9 @@ class MaglevGraphBuilder {
void VisitBinaryOperation(); void VisitBinaryOperation();
template <Operation kOperation> template <Operation kOperation>
void VisitBinarySmiOperation(); void VisitBinarySmiOperation();
bool TryBuildCompareOperationBranch(Operation operation, ValueNode* left,
ValueNode* right);
template <Operation kOperation> template <Operation kOperation>
void VisitCompareOperation(); void VisitCompareOperation();
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "src/codegen/macro-assembler-inl.h" #include "src/codegen/macro-assembler-inl.h"
#include "src/codegen/register.h" #include "src/codegen/register.h"
#include "src/codegen/reglist.h" #include "src/codegen/reglist.h"
#include "src/codegen/x64/assembler-x64.h"
#include "src/common/globals.h" #include "src/common/globals.h"
#include "src/compiler/backend/instruction.h" #include "src/compiler/backend/instruction.h"
#include "src/ic/handler-configuration.h" #include "src/ic/handler-configuration.h"
...@@ -1647,11 +1648,36 @@ void BranchIfTrue::GenerateCode(MaglevCodeGenState* code_gen_state, ...@@ -1647,11 +1648,36 @@ void BranchIfTrue::GenerateCode(MaglevCodeGenState* code_gen_state,
} }
void BranchIfInt32Compare::AllocateVreg(MaglevVregAllocationState* vreg_state, void BranchIfInt32Compare::AllocateVreg(MaglevVregAllocationState* vreg_state,
const ProcessingState& state) {} const ProcessingState& state) {
UseRegister(left_input());
UseRegister(right_input());
}
void BranchIfInt32Compare::GenerateCode(MaglevCodeGenState* code_gen_state, void BranchIfInt32Compare::GenerateCode(MaglevCodeGenState* code_gen_state,
const ProcessingState& state) { const ProcessingState& state) {
USE(operation_); Register left = ToRegister(left_input());
UNREACHABLE(); Register right = ToRegister(right_input());
auto* next_block = state.next_block();
__ cmpl(left, right);
// We don't have any branch probability information, so try to jump
// over whatever the next block emitted is.
if (if_false() == next_block) {
// Jump over the false block if true, otherwise fall through into it.
__ j(Int32ConditionFor(operation_), if_true()->label());
} else {
// Jump to the false block if true.
__ j(NegateCondition(Int32ConditionFor(operation_)), if_false()->label());
// Jump to the true block if it's not the next block.
if (if_true() != next_block) {
__ jmp(if_true()->label());
}
}
}
void BranchIfInt32Compare::PrintParams(
std::ostream& os, MaglevGraphLabeller* graph_labeller) const {
os << "(" << operation_ << ")";
} }
void BranchIfToBooleanTrue::AllocateVreg(MaglevVregAllocationState* vreg_state, void BranchIfToBooleanTrue::AllocateVreg(MaglevVregAllocationState* vreg_state,
......
...@@ -2277,7 +2277,7 @@ class BranchIfInt32Compare ...@@ -2277,7 +2277,7 @@ class BranchIfInt32Compare
void AllocateVreg(MaglevVregAllocationState*, const ProcessingState&); void AllocateVreg(MaglevVregAllocationState*, const ProcessingState&);
void GenerateCode(MaglevCodeGenState*, const ProcessingState&); void GenerateCode(MaglevCodeGenState*, const ProcessingState&);
void PrintParams(std::ostream&, MaglevGraphLabeller*) const {} void PrintParams(std::ostream&, MaglevGraphLabeller*) const;
private: private:
Operation operation_; Operation operation_;
......
// Copyright 2022 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax --maglev --no-stress-opt
function foo(x,y) {
if (x < y) {
return 42;
}
return 24;
}
%PrepareFunctionForOptimization(foo);
assertEquals(42, foo(1,2));
assertEquals(24, foo(6,2));
%OptimizeMaglevOnNextCall(foo);
assertEquals(42, foo(1,2));
assertEquals(24, foo(6,2));
function bar(x,y) {
if (!(x >= y)) {
return 42;
}
return 24;
}
%PrepareFunctionForOptimization(bar);
assertEquals(42, bar(1,2));
assertEquals(24, bar(6,2));
%OptimizeMaglevOnNextCall(bar);
assertEquals(42, bar(1,2));
assertEquals(24, bar(6,2));
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment