Commit dc1d0796 authored by Andreas Haas's avatar Andreas Haas Committed by Commit Bot

[turbofan] Optimize verification of switch nodes

I changed the verification algorithm of switch nodes from a quadratic
algorithm to a linear one. On my machine this speeds up the test from
17 seconds to 2 seconds in the x64.optdebug build.

R=mslekova@chromium.org

Bug: v8:9810
Change-Id: I952d3fcc641b4e269b8ebac8f65fe545c6062587
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1905768
Commit-Queue: Andreas Haas <ahaas@chromium.org>
Reviewed-by: 's avatarMaya Lekova <mslekova@chromium.org>
Cr-Commit-Position: refs/heads/master@{#64877}
parent 1b04772f
...@@ -38,6 +38,7 @@ class Verifier::Visitor { ...@@ -38,6 +38,7 @@ class Verifier::Visitor {
check_inputs(check_inputs), check_inputs(check_inputs),
code_type(code_type) {} code_type(code_type) {}
void CheckSwitch(Node* node, const AllNodes& all);
void Check(Node* node, const AllNodes& all); void Check(Node* node, const AllNodes& all);
Zone* zone; Zone* zone;
...@@ -92,6 +93,47 @@ class Verifier::Visitor { ...@@ -92,6 +93,47 @@ class Verifier::Visitor {
} }
}; };
void Verifier::Visitor::CheckSwitch(Node* node, const AllNodes& all) {
// Count the number of {kIfValue} uses.
int case_count = 0;
bool expect_default = true;
// Data structure to check that each {kIfValue} has a unique value.
std::unordered_set<int32_t> if_value_parameters;
Node::Uses uses = node->uses();
for (const Node* use : uses) {
CHECK(all.IsLive(use));
switch (use->opcode()) {
case IrOpcode::kIfValue: {
// Check if each value is unique.
CHECK(
if_value_parameters.emplace(IfValueParametersOf(use->op()).value())
.second);
++case_count;
break;
}
case IrOpcode::kIfDefault: {
// We expect exactly one {kIfDefault}.
CHECK(expect_default);
expect_default = false;
break;
}
default: {
FATAL("Switch #%d illegally used by #%d:%s", node->id(), use->id(),
use->op()->mnemonic());
break;
}
}
}
CHECK(!expect_default);
// + 1 because of the one {kIfDefault}.
CHECK_EQ(node->op()->ControlOutputCount(), case_count + 1);
// Type is empty.
CheckNotTyped(node);
}
void Verifier::Visitor::Check(Node* node, const AllNodes& all) { void Verifier::Visitor::Check(Node* node, const AllNodes& all) {
int value_count = node->op()->ValueInputCount(); int value_count = node->op()->ValueInputCount();
int context_count = OperatorProperties::GetContextInputCount(node->op()); int context_count = OperatorProperties::GetContextInputCount(node->op());
...@@ -289,36 +331,7 @@ void Verifier::Visitor::Check(Node* node, const AllNodes& all) { ...@@ -289,36 +331,7 @@ void Verifier::Visitor::Check(Node* node, const AllNodes& all) {
break; break;
} }
case IrOpcode::kSwitch: { case IrOpcode::kSwitch: {
// Switch uses are Case and Default. CheckSwitch(node, all);
int count_case = 0, count_default = 0;
for (const Node* use : node->uses()) {
CHECK(all.IsLive(use));
switch (use->opcode()) {
case IrOpcode::kIfValue: {
for (const Node* user : node->uses()) {
if (user != use && user->opcode() == IrOpcode::kIfValue) {
CHECK_NE(IfValueParametersOf(use->op()).value(),
IfValueParametersOf(user->op()).value());
}
}
++count_case;
break;
}
case IrOpcode::kIfDefault: {
++count_default;
break;
}
default: {
FATAL("Switch #%d illegally used by #%d:%s", node->id(), use->id(),
use->op()->mnemonic());
break;
}
}
}
CHECK_EQ(1, count_default);
CHECK_EQ(node->op()->ControlOutputCount(), count_case + count_default);
// Type is empty.
CheckNotTyped(node);
break; break;
} }
case IrOpcode::kIfValue: case IrOpcode::kIfValue:
......
...@@ -53,11 +53,6 @@ ...@@ -53,11 +53,6 @@
'conversions': [SKIP], 'conversions': [SKIP],
}], # '(arch == mipsel or arch == mips64el or arch == mips or arch == mips64) and not simulator_run' }], # '(arch == mipsel or arch == mips64el or arch == mips or arch == mips64) and not simulator_run'
['arch == arm and not simulator_run', {
# Too slow on chromebooks.
'br_table': [SKIP],
}], # 'arch == arm and not simulator_run'
['arch == ppc or arch == ppc64', { ['arch == ppc or arch == ppc64', {
# These tests fail because ppc float min and max doesn't convert sNaN to qNaN. # These tests fail because ppc float min and max doesn't convert sNaN to qNaN.
'f32': [SKIP], 'f32': [SKIP],
......
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