blob: d22c94c93f855610ff6d3e7b01e6f48161635593 [file] [log] [blame]
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// Test that multiple comparisons involving the same uint32 value
// with different constants do not generate multiple IntConverter
// instructions, only a sequence of 'Branch(EqualityCompare(...))'.
// Regression test for https://github.com/dart-lang/sdk/issues/56839.
import 'package:vm/testing/il_matchers.dart';
class Token {
Token(TokenType type, int offset)
: typeAndOffset = ((offset << 8) | type.index);
int typeAndOffset;
int get typeIndex => typeAndOffset & 0xff;
}
class TokenType {
static const TokenType T10 = const TokenType(10, 'T10');
static const TokenType T20 = const TokenType(20, 'T20');
static const TokenType T30 = const TokenType(30, 'T30');
static const TokenType T40 = const TokenType(40, 'T40');
static const TokenType T50 = const TokenType(50, 'T50');
static const TokenType T60 = const TokenType(50, 'T60');
static const TokenType T70 = const TokenType(50, 'T70');
const TokenType(this.index, this.name);
final int index;
final String name;
}
extension TokenIsAExtension on Token {
@pragma("vm:prefer-inline")
bool isA(TokenType value) {
return value.index == typeIndex;
}
}
@pragma('vm:never-inline')
@pragma('vm:testing:print-flow-graph')
bool looksLikeExpressionStart(Token next) =>
next.isA(TokenType.T10) ||
next.isA(TokenType.T20) ||
next.isA(TokenType.T30) ||
next.isA(TokenType.T40) ||
next.isA(TokenType.T50);
void matchIL$looksLikeExpressionStart(FlowGraph graph) {
graph.match([
match.block('Graph', [
'int 255' << match.UnboxedConstant(value: 255),
'int 10' << match.UnboxedConstant(value: 10),
'int 20' << match.UnboxedConstant(value: 20),
'int 30' << match.UnboxedConstant(value: 30),
'int 40' << match.UnboxedConstant(value: 40),
'int 50' << match.UnboxedConstant(value: 50),
]),
match.block('Function', [
'value' << match.Parameter(index: 0),
'typeAndOffset' << match.LoadField(slot: 'typeAndOffset'),
'typeAndOffset_u32' <<
match.IntConverter('typeAndOffset', from: 'int64', to: 'uint32'),
'typeIndex' <<
match.BinaryUint32Op('typeAndOffset_u32', 'int 255', op_kind: '&'),
match.Branch(
match.EqualityCompare('typeIndex', 'int 10', kind: '=='),
ifTrue: 'B9',
ifFalse: 'B4',
),
]),
'B9' << match.block('Target', [match.Goto('B8')]),
'B4' <<
match.block('Target', [
match.Branch(
match.EqualityCompare('typeIndex', 'int 20', kind: '=='),
ifTrue: 'B10',
ifFalse: 'B5',
),
]),
'B10' << match.block('Target', [match.Goto('B8')]),
'B5' <<
match.block('Target', [
match.Branch(
match.EqualityCompare('typeIndex', 'int 30', kind: '=='),
ifTrue: 'B11',
ifFalse: 'B6',
),
]),
'B11' << match.block('Target', [match.Goto('B8')]),
'B6' <<
match.block('Target', [
match.Branch(
match.EqualityCompare('typeIndex', 'int 40', kind: '=='),
ifTrue: 'B12',
ifFalse: 'B7',
),
]),
'B12' << match.block('Target', [match.Goto('B8')]),
'B8' << match.block('Join', [match.Goto('B3')]),
'B7' <<
match.block('Target', [
'v23' << match.EqualityCompare('typeIndex', 'int 50', kind: '=='),
match.Goto('B3'),
]),
'B3' <<
match.block('Join', [
'v14' << match.Phi('v23', match.any),
match.DartReturn('v14'),
]),
]);
}
void main() {
looksLikeExpressionStart(Token(TokenType.T10, 5));
looksLikeExpressionStart(Token(TokenType.T60, 10));
}