Skip to content

Commit

Permalink
[dart2wasm] Add -O/--optimization-level flag to dart compile wasm
Browse files Browse the repository at this point in the history
We make the meaning of -O{0,1,2,3,4} to be similar to what dart2js has.
We also make the pkg/dart2wasm/tool/compile_benchmark accept the same flags.

Follow-up CLs will migrate Dart CI / Golem / flutter to use -O flags.

Change-Id: Id37476c596ec7483e633c7db9eec96438315e919
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/348165
Reviewed-by: Slava Egorov <vegorov@google.com>
  • Loading branch information
mkustermann committed Jan 25, 2024
1 parent 7b37838 commit 92d53c4
Show file tree
Hide file tree
Showing 2 changed files with 159 additions and 61 deletions.
106 changes: 73 additions & 33 deletions pkg/dart2wasm/tool/compile_benchmark
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,46 @@

set -e

function follow_links() {
file="$1"
while [ -h "$file" ]; do
# On Mac OS, readlink -f doesn't work.
file="$(readlink "$file")"
done
echo "$file"
}

# Unlike $0, $BASH_SOURCE points to the absolute path of this file.
PROG_NAME="$(follow_links "$BASH_SOURCE")"

# Handle the case where dart-sdk/bin has been symlinked to.
PROG_DIR="$(cd "${PROG_NAME%/*}" ; pwd -P)"
SDK_DIR="$(cd "${PROG_DIR}/../../.." ; pwd -P)"

# Locate build directory, containing executables, snapshots and platform dill.
if [[ `uname` == 'Darwin' ]]; then
OUT_DIR="$SDK_DIR/xcodebuild"
else
OUT_DIR="$SDK_DIR/out"
fi
DART_CONFIGURATION=${DART_CONFIGURATION:-ReleaseX64}
BIN_DIR="$OUT_DIR/$DART_CONFIGURATION"

BINARYEN="$BIN_DIR/wasm-opt"
DART_AOT_RUNTIME="$BIN_DIR/dart_precompiled_runtime"
SDK_ARG="--dart-sdk=$SDK_DIR"

function find_flags {
echo -en "$(sed -n "/$1 =/,/end of $1/ p" $SDK_DIR/pkg/dartdev/lib/src/commands/compile.dart | sed '1d' | sed '$d' | tr '\n' ' ' | sed 's#\s\+# #g' | sed 's#^\s\+##' | sed 's#\s\+$##')"
}
# Use same flags as `dart compile exe`
BINARYEN_FLAGS=($(find_flags 'binaryenFlags'))
OPT_FLAGS_L0=($(find_flags 'optimizationLevel0Flags'))
OPT_FLAGS_L1=($(find_flags 'optimizationLevel1Flags'))
OPT_FLAGS_L2=($(find_flags 'optimizationLevel2Flags'))
OPT_FLAGS_L3=($(find_flags 'optimizationLevel3Flags'))
OPT_FLAGS_L4=($(find_flags 'optimizationLevel4Flags'))

RUN_BINARYEN=1
COMPILE_BENCHMARK_BASE_NAME=""
PLATFORM_FILENAME="dart2wasm_platform.dill"
Expand Down Expand Up @@ -38,11 +78,43 @@ while [ $# -gt 0 ]; do
shift
;;

-O0 | --optimization-level=0)
DART2WASM_ARGS+=(${OPT_FLAGS_L0[@]})
RUN_BINARYEN=0
shift
;;

-O1 | --optimization-level=1)
DART2WASM_ARGS+=(${OPT_FLAGS_L1[@]})
RUN_BINARYEN=1
shift
;;

-O2 | --optimization-level=2)
DART2WASM_ARGS+=(${OPT_FLAGS_L2[@]})
RUN_BINARYEN=1
shift
;;

-O3 | --optimization-level=3)
DART2WASM_ARGS+=(${OPT_FLAGS_L3[@]})
RUN_BINARYEN=1
shift
;;

-O4 | --optimization-level=4)
DART2WASM_ARGS+=(${OPT_FLAGS_L4[@]})
RUN_BINARYEN=1
shift
;;

# TODO: Remove this deprecated flag
--optimize)
RUN_BINARYEN=1
shift
;;

# TODO: Remove this deprecated flag
--no-optimize)
RUN_BINARYEN=0
shift
Expand Down Expand Up @@ -83,40 +155,8 @@ if [ -z "$DART_FILE" -o -z "$WASM_FILE" ]; then
fi


function follow_links() {
file="$1"
while [ -h "$file" ]; do
# On Mac OS, readlink -f doesn't work.
file="$(readlink "$file")"
done
echo "$file"
}

# Unlike $0, $BASH_SOURCE points to the absolute path of this file.
PROG_NAME="$(follow_links "$BASH_SOURCE")"

# Handle the case where dart-sdk/bin has been symlinked to.
PROG_DIR="$(cd "${PROG_NAME%/*}" ; pwd -P)"
SDK_DIR="$(cd "${PROG_DIR}/../../.." ; pwd -P)"

# Use same binaryen flags as `dart compile exe`
BINARYEN_FLAGS="$(sed -n '/binaryenFlags =/,/end of binaryenFlags/ p' $SDK_DIR/pkg/dartdev/lib/src/commands/compile.dart | sed '1d' | sed '$d' | tr '\n' ' ')"

# Locate build directory, containing executables, snapshots and platform dill.
if [[ `uname` == 'Darwin' ]]; then
OUT_DIR="$SDK_DIR/xcodebuild"
else
OUT_DIR="$SDK_DIR/out"
fi
DART_CONFIGURATION=${DART_CONFIGURATION:-ReleaseX64}
BIN_DIR="$OUT_DIR/$DART_CONFIGURATION"

BINARYEN="$BIN_DIR/wasm-opt"
DART_AOT_RUNTIME="$BIN_DIR/dart_precompiled_runtime"
DART2WASM_AOT_SNAPSHOT="$BIN_DIR/$SNAPSHOT_NAME.snapshot"

PLATFORM_ARG="--platform=$BIN_DIR/$PLATFORM_FILENAME"
SDK_ARG="--dart-sdk=$SDK_DIR"
DART2WASM_AOT_SNAPSHOT="$BIN_DIR/$SNAPSHOT_NAME.snapshot"

function measure() {
set +e
Expand Down
114 changes: 86 additions & 28 deletions pkg/dartdev/lib/src/commands/compile.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,28 +19,6 @@ import '../native_assets.dart';
import '../sdk.dart';
import '../utils.dart';

// The unique place where we store dart2wasm binaryen flags.
//
// Other uses (e.g. in shell scripts) will grep in this file for the flags. So
// please keep it as a simple multi-line string of flags.
final List<String> binaryenFlags = '''
--all-features
--closed-world
--traps-never-happen
--type-unfinalizing
-O3
--type-ssa
--gufa
-O3
--type-merging
-O1
--type-finalizing
''' // end of binaryenFlags
.split('\n')
.map((line) => line.trim())
.where((line) => line.isNotEmpty)
.toList();

const int compileErrorExitCode = 64;

class Option {
Expand Down Expand Up @@ -435,6 +413,57 @@ class CompileWasmCommand extends CompileSubcommandCommand {
static const String help =
'Compile Dart to a WebAssembly/WasmGC module (EXPERIMENTAL).';

// The unique place where we store various flags for dart2wasm & binaryen.
//
// Other uses (e.g. pkg/dart2wasm/tool/compile_benchmark) will grep in this
// file for the flags. So please keep the formatting.

final List<String> binaryenFlags = _flagList('''
--all-features
--closed-world
--traps-never-happen
--type-unfinalizing
-O3
--type-ssa
--gufa
-O3
--type-merging
-O1
--type-finalizing
'''); // end of binaryenFlags

final List<String> optimizationLevel0Flags = _flagList('''
--no-inlining
'''); // end of optimizationLevel0Flags

final List<String> optimizationLevel1Flags = _flagList('''
--inlining
'''); // end of optimizationLevel1Flags

final List<String> optimizationLevel2Flags = _flagList('''
--inlining
--minify
'''); // end of optimizationLevel2Flags

final List<String> optimizationLevel3Flags = _flagList('''
--inlining
--minify
--omit-implicit-checks
'''); // end of optimizationLevel3Flags

final List<String> optimizationLevel4Flags = _flagList('''
--inlining
--minify
--omit-implicit-checks
--omit-explicit-checks
'''); // end of optimizationLevel4Flags

static List<String> _flagList(String lines) => lines
.split('\n')
.map((line) => line.trim())
.where((line) => line.isNotEmpty)
.toList();

CompileWasmCommand({bool verbose = false})
: super(commandName, help, verbose, hidden: !verbose) {
argParser
Expand All @@ -450,6 +479,7 @@ class CompileWasmCommand extends CompileSubcommandCommand {
help: 'Generate minified output.',
hide: !verbose,
)
// TODO: Deprecate this flag.
..addFlag(
'optimize',
defaultsTo: true,
Expand Down Expand Up @@ -500,6 +530,16 @@ class CompileWasmCommand extends CompileSubcommandCommand {
valueHelp: 'page count',
hide: !verbose,
)
..addOption(
'optimization-level',
abbr: 'O',
help: 'Controls optimizations that can help reduce code-size and '
'improve performance of the generated code.',
allowed: ['0', '1', '2', '3', '4'],
defaultsTo: null, // TODO: Set this to '1'
valueHelp: 'level',
hide: !verbose,
)
..addOption(
packagesOption.flag,
abbr: packagesOption.abbr,
Expand Down Expand Up @@ -575,24 +615,42 @@ class CompileWasmCommand extends CompileSubcommandCommand {
}
}

final defaultOptimizationLevel = args['optimize'] ? '1' : '0';
final optimizationLevel =
int.parse(args['optimization-level'] ?? defaultOptimizationLevel);
final runWasmOpt = optimizationLevel >= 1;

final dart2wasmCommand = [
sdk.dartAotRuntime,
sdk.dart2wasmSnapshot,

'--libraries-spec=${sdk.librariesJson}',
'--dart-sdk=$sdkPath',
if (verbose) '--verbose',
if (packages != null) '--packages=$packages',
if (args['enable-asserts']) '--enable-asserts',
if (args['print-wasm']) '--print-wasm',
if (args['print-kernel']) '--print-kernel',
if (args['omit-type-checks']) '--omit-type-checks',
if (args['name-section']) '--name-section',
if (args['minify']) '--minify',
if (args['enable-asserts']) '--enable-asserts',
for (final define in defines) '-D$define',
if (maxPages != null) ...[
'--import-shared-memory',
'--shared-memory-max-pages=$maxPages',
],
for (final define in defines) '-D$define',

// First we pass flags based on the optimization level.
...switch (optimizationLevel) {
0 => optimizationLevel0Flags,
1 => optimizationLevel1Flags,
2 => optimizationLevel2Flags,
3 => optimizationLevel3Flags,
4 => optimizationLevel4Flags,
_ => throw 'unreachable',
},
// Then we pass flags that were opted into explicitly.
if (args['omit-type-checks']) '--omit-type-checks',
if (args['name-section']) '--name-section',
if (args['minify']) '--minify',

path.absolute(sourcePath),
outputFile,
];
Expand All @@ -608,7 +666,7 @@ class CompileWasmCommand extends CompileSubcommandCommand {
return compileErrorExitCode;
}

if (args['optimize']) {
if (runWasmOpt) {
final unoptFile = '$outputFileBasename.unopt.wasm';
File(outputFile).renameSync(unoptFile);

Expand Down

0 comments on commit 92d53c4

Please sign in to comment.