[vm/compiler] Remove unnecessary type check from optimized switches

Switch optimization now relies on static type of the tested value,
so it is safe to omit the type check (with sound null safety) or
reduce it to a null check (without sound null safety).

TEST=co19/LanguageFeatures/Patterns/Exhaustiveness/exhaustiveness_enum_A01_t01
Fixes https://github.com/dart-lang/sdk/issues/52422

Change-Id: Ic93f4f212bee9ed3bfe5035f3c8d7535274c2f63
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/304102
Commit-Queue: Alexander Markov <alexmarkov@google.com>
Reviewed-by: Alexander Aprelev <aam@google.com>
This commit is contained in:
Alexander Markov 2023-05-17 17:11:28 +00:00 committed by Commit Queue
parent 027d0738d0
commit 43ce5487c1

View file

@ -5072,30 +5072,23 @@ Fragment StreamingFlowGraphBuilder::BuildOptimizedSwitchPrelude(
SwitchHelper* helper,
JoinEntryInstr* join) {
const TokenPosition pos = helper->position();
// We need to check that the switch variable is of the correct type.
// If it is not, we go to [join] which is either the default case or
// the exit of the switch statement.
TargetEntryInstr* then_entry;
TargetEntryInstr* otherwise_entry;
const AbstractType& expression_type = helper->expression_type();
ASSERT(dart::SimpleInstanceOfType(expression_type));
Fragment instructions;
instructions += LoadLocal(scopes()->switch_variable);
instructions += Constant(expression_type);
instructions += InstanceCall(
pos, Library::PrivateCoreLibName(Symbols::_simpleInstanceOf()),
Token::kIS, /*argument_count=*/2,
/*checked_argument_count=*/2);
instructions += BranchIfTrue(&then_entry, &otherwise_entry, /*negate=*/false);
Fragment otherwise_instructions(otherwise_entry);
otherwise_instructions += Goto(join);
if (!IG->null_safety()) {
// Without sound null safety we need to check that the switch variable is
// not null. If it is null, we go to [join] which is either the default
// case or the exit of the switch statement.
TargetEntryInstr* null_entry;
TargetEntryInstr* non_null_entry;
instructions = Fragment(instructions.entry, then_entry);
instructions += LoadLocal(scopes()->switch_variable);
instructions += BranchIfNull(&null_entry, &non_null_entry);
Fragment null_instructions(null_entry);
null_instructions += Goto(join);
instructions = Fragment(instructions.entry, non_null_entry);
}
if (helper->is_enum_switch()) {
// For an enum switch, we need to load the enum index from the switch
@ -5260,6 +5253,10 @@ Fragment StreamingFlowGraphBuilder::BuildBinarySearchSwitch(
stack.Add(
SwitchRange::Branch(range.min(), middle, lower_branch_instructions));
}
if (current_instructions.is_empty()) {
current_instructions = branch_instructions;
}
}
return Fragment(current_instructions.entry, join_instructions.current);