mirror of
https://github.com/dart-lang/sdk
synced 2024-11-05 18:22:09 +00:00
[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:
parent
027d0738d0
commit
43ce5487c1
1 changed files with 18 additions and 21 deletions
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue