| // 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); |
| } |