diff --git a/src/compiler/backend/code-generator.cc b/src/compiler/backend/code-generator.cc index 9f1f45b90c..ee75ca27bc 100644 --- a/src/compiler/backend/code-generator.cc +++ b/src/compiler/backend/code-generator.cc @@ -430,6 +430,7 @@ void CodeGenerator::AssembleCode() { result_ = kSuccess; } +#ifndef V8_TARGET_ARCH_X64 void CodeGenerator::AssembleArchBinarySearchSwitchRange( Register input, RpoNumber def_block, std::pair* begin, std::pair* end) { @@ -448,6 +449,7 @@ void CodeGenerator::AssembleArchBinarySearchSwitchRange( masm()->bind(&less_label); AssembleArchBinarySearchSwitchRange(input, def_block, begin, middle); } +#endif // V8_TARGET_ARCH_X64 void CodeGenerator::AssembleArchJump(RpoNumber target) { if (!IsNextInAssemblyOrder(target)) diff --git a/src/compiler/backend/code-generator.h b/src/compiler/backend/code-generator.h index f6feb42378..20cc045b11 100644 --- a/src/compiler/backend/code-generator.h +++ b/src/compiler/backend/code-generator.h @@ -278,9 +278,15 @@ class V8_EXPORT_PRIVATE CodeGenerator final : public GapResolver::Assembler { #if V8_ENABLE_WEBASSEMBLY void AssembleArchTrap(Instruction* instr, FlagsCondition condition); #endif // V8_ENABLE_WEBASSEMBLY +#if V8_TARGET_ARCH_X64 + void AssembleArchBinarySearchSwitchRange( + Register input, RpoNumber def_block, std::pair* begin, + std::pair* end, base::Optional& last_cmp_value); +#else void AssembleArchBinarySearchSwitchRange(Register input, RpoNumber def_block, std::pair* begin, std::pair* end); +#endif // V8_TARGET_ARCH_X64 void AssembleArchBinarySearchSwitch(Instruction* instr); void AssembleArchTableSwitch(Instruction* instr); diff --git a/src/compiler/backend/x64/code-generator-x64.cc b/src/compiler/backend/x64/code-generator-x64.cc index 42d846a97f..7924a6fe60 100644 --- a/src/compiler/backend/x64/code-generator-x64.cc +++ b/src/compiler/backend/x64/code-generator-x64.cc @@ -4,6 +4,7 @@ #include +#include "src/base/optional.h" #include "src/base/overflowing-math.h" #include "src/codegen/assembler.h" #include "src/codegen/cpu-features.h" @@ -4746,6 +4747,34 @@ void CodeGenerator::AssembleArchBoolean(Instruction* instr, __ bind(&done); } +void CodeGenerator::AssembleArchBinarySearchSwitchRange( + Register input, RpoNumber def_block, std::pair* begin, + std::pair* end, base::Optional& last_cmp_value) { + if (end - begin < kBinarySearchSwitchMinimalCases) { + if (last_cmp_value && *last_cmp_value == begin->first) { + // No need to do another repeat cmp. + masm()->j(equal, begin->second); + ++begin; + } + + while (begin != end) { + masm()->JumpIfEqual(input, begin->first, begin->second); + ++begin; + } + AssembleArchJumpRegardlessOfAssemblyOrder(def_block); + return; + } + auto middle = begin + (end - begin) / 2; + Label less_label; + masm()->JumpIfLessThan(input, middle->first, &less_label); + last_cmp_value = middle->first; + AssembleArchBinarySearchSwitchRange(input, def_block, middle, end, + last_cmp_value); + masm()->bind(&less_label); + AssembleArchBinarySearchSwitchRange(input, def_block, begin, middle, + last_cmp_value); +} + void CodeGenerator::AssembleArchBinarySearchSwitch(Instruction* instr) { X64OperandConverter i(this, instr); Register input = i.InputRegister(0); @@ -4753,8 +4782,10 @@ void CodeGenerator::AssembleArchBinarySearchSwitch(Instruction* instr) { for (size_t index = 2; index < instr->InputCount(); index += 2) { cases.push_back({i.InputInt32(index + 0), GetLabel(i.InputRpo(index + 1))}); } + base::Optional last_cmp_value; AssembleArchBinarySearchSwitchRange(input, i.InputRpo(1), cases.data(), - cases.data() + cases.size()); + cases.data() + cases.size(), + last_cmp_value); } void CodeGenerator::AssembleArchTableSwitch(Instruction* instr) {