blob: a6d3338dfc10bc58942833678d62e0f5a75c539c [file] [log] [blame]
// Copyright (c) 2025, 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.
/*member: main:ignore*/
void main() {
for (final functions in [
[cse_000, cse_001, cse_010, cse_011, cse_100, cse_101, cse_110, cse_111],
[dce_000, dce_001, dce_010, dce_011, dce_100, dce_101, dce_110, dce_111],
[cse_dce_000, cse_dce_001, cse_dce_010, cse_dce_011],
[cse_dce_100, cse_dce_101, cse_dce_110, cse_dce_111],
]) {
for (final f in functions) {
f(123);
f('x');
}
}
print([sink1, sink2]);
}
Object? sink1;
Object? sink2;
int gI = 0;
/// [source] is not idempotent so would normally not be eligible for CSE or DCE.
/*member: source:ignore*/
@pragma('dart2js:never-inline')
Object? source(Object? o) {
++gI;
sink1 = o;
return o is num ? gI : o;
}
/// Basic 'f' functions are the same function body that calls [source] and casts
/// the result, but with all combinations of inlining and allow-cse and
/// allow-dce annotations.
///
/// fABC:
/// A: 1: inlined (0 not inlined)
/// B: 1: has allow-dce
/// C: 1: has allow-cse
///
/// So f000 and f100 serve as a baseline for comparing the effects of the
/// allow-cse and allow-dce annotations.
///
/// These functions are used in three ways:
///
/// cse_ABC calls fABC twice and uses the results
/// dce_ABC calls fABC once and ignores the result
/// cse_dce_ABC calls fABC twice and ignores both results
@pragma('dart2js:never-inline')
/*member: f000:function(o) {
return A._asInt(A.source(o));
}*/
int f000(o) => source(o) as int;
@pragma('dart2js:never-inline')
@pragma('dart2js:allow-cse')
/*member: f001:function(o) {
return A._asInt(A.source(o));
}*/
int f001(o) => source(o) as int;
@pragma('dart2js:never-inline')
@pragma('dart2js:allow-dce')
/*member: f010:function(o) {
return A._asInt(A.source(o));
}*/
int f010(o) => source(o) as int;
@pragma('dart2js:never-inline')
@pragma('dart2js:allow-cse')
@pragma('dart2js:allow-dce')
/*member: f011:function(o) {
return A._asInt(A.source(o));
}*/
int f011(o) => source(o) as int;
@pragma('dart2js:prefer-inline')
int f100(o) => source(o) as int;
@pragma('dart2js:prefer-inline')
@pragma('dart2js:allow-cse')
/*member: f101:function(o) {
return A._asInt(A.source(o));
}*/
int f101(o) => source(o) as int;
@pragma('dart2js:prefer-inline')
@pragma('dart2js:allow-dce')
/*member: f110:function(o) {
return A._asInt(A.source(o));
}*/
int f110(o) => source(o) as int;
@pragma('dart2js:prefer-inline')
@pragma('dart2js:allow-cse')
@pragma('dart2js:allow-dce')
/*member: f111:function(o) {
return A._asInt(A.source(o));
}*/
int f111(o) => source(o) as int;
/*member: cse_000:function(x) {
$.sink1 = A.f000(x);
$.sink2 = A.f000(x);
}*/
void cse_000(x) {
// Expect two uninlined calls.
sink1 = f000(x);
sink2 = f000(x);
}
/*member: cse_001:function(x) {
$.sink2 = $.sink1 = A.f001(x);
}*/
void cse_001(x) {
// Expect one call that is reused.
sink1 = f001(x);
sink2 = f001(x);
}
/*member: cse_010:function(x) {
$.sink1 = A.f010(x);
$.sink2 = A.f010(x);
}*/
void cse_010(x) {
sink1 = f010(x);
sink2 = f010(x);
}
/*member: cse_011:function(x) {
$.sink2 = $.sink1 = A.f011(x);
}*/
void cse_011(x) {
// Expect one call that is reused.
sink1 = f011(x);
sink2 = f011(x);
}
/*member: cse_100:function(x) {
$.sink1 = A._asInt(A.source(x));
$.sink2 = A._asInt(A.source(x));
}*/
void cse_100(x) {
// Expect two inlined calls with no shared subexpressions.
sink1 = f100(x);
sink2 = f100(x);
}
/*member: cse_101:function(x) {
$.sink2 = $.sink1 = A.f101(x);
}*/
void cse_101(x) {
// Expect one call, possibly inlined.
sink1 = f101(x);
sink2 = f101(x);
}
/*member: cse_110:function(x) {
$.sink1 = A.f110(x);
$.sink2 = A.f110(x);
}*/
void cse_110(x) {
// Expect two calls; possibly inlined, with no shared subexpressions.
sink1 = f110(x);
sink2 = f110(x);
}
/*member: cse_111:function(x) {
$.sink2 = $.sink1 = A.f111(x);
}*/
void cse_111(x) {
// Expect one call.
sink1 = f111(x);
sink2 = f111(x);
}
/*member: dce_000:function(x) {
A.f000(x);
}*/
void dce_000(x) {
f000(x);
}
/*member: dce_001:function(x) {
A.f001(x);
}*/
void dce_001(x) {
f001(x);
}
/*member: dce_010:function(x) {
}*/
void dce_010(x) {
// Expect deleted call.
f010(x);
}
/*member: dce_011:function(x) {
}*/
void dce_011(x) {
// Expect deleted call.
f011(x);
}
/*member: dce_100:function(x) {
A._asInt(A.source(x));
}*/
void dce_100(x) {
// Expect inlined call.
f100(x);
}
/*member: dce_101:function(x) {
A.f101(x);
}*/
void dce_101(x) {
// Expect one call, possibly inlined.
f101(x);
}
/*member: dce_110:function(x) {
}*/
void dce_110(x) {
// Expect deleted call.
f110(x);
}
/*member: dce_111:function(x) {
}*/
void dce_111(x) {
// Expect deleted call.
f111(x);
}
/*member: cse_dce_000:function(x) {
A.f000(x);
A.f000(x);
}*/
void cse_dce_000(x) {
// Expect two calls.
f000(x);
f000(x);
}
/*member: cse_dce_001:function(x) {
A.f001(x);
}*/
void cse_dce_001(x) {
// Expect one call.
f001(x);
f001(x);
}
/*member: cse_dce_010:function(x) {
}*/
void cse_dce_010(x) {
// Expect empty body - both calls deleted.
f010(x);
f010(x);
}
/*member: cse_dce_011:function(x) {
}*/
void cse_dce_011(x) {
// Expect empty body - both calls deleted.
f011(x);
f011(x);
}
/*member: cse_dce_100:function(x) {
A._asInt(A.source(x));
A._asInt(A.source(x));
}*/
void cse_dce_100(x) {
// Expect both calls inlined.
f100(x);
f100(x);
}
/*member: cse_dce_101:function(x) {
A.f101(x);
}*/
void cse_dce_101(x) {
// Expect call or one copy of inlined function.
f101(x);
f101(x);
}
/*member: cse_dce_110:function(x) {
}*/
void cse_dce_110(x) {
// Expect empty body - both calls deleted.
f110(x);
f110(x);
}
/*member: cse_dce_111:function(x) {
}*/
void cse_dce_111(x) {
// Expect empty body - both calls deleted.
f111(x);
f111(x);
}