Skip to content

Commit 082bc3d

Browse files
osa1Commit Queue
authored andcommitted
[dart2wasm] Improve -O0 code gen for inline unary ops
When inlining an unary operator, evaluate the the operator in compile time when the arugment is a literal or constant. This helps with debug mode code size, especially with large literals. The test `co19/LibTest/core/List/sort_A01_t06.test.dart` becomes 492,496 lines of .wat, from 558,080. Also removes the intrinsic `_toInt`, which is no longer used. Example: void main() { print(~123); print(123.toDouble()); print(12.34.floorToDouble()); print(12.34.ceilToDouble()); print(12.34.truncateToDouble()); } Diff of wat: --- before 2024-10-28 12:21:08.537971233 +0100 +++ after 2024-10-28 12:17:01.965688861 +0100 @@ -4,41 +4,35 @@ (local $var2 f64) (local $var3 f64) (local $var4 f64) - i64.const 123 - i64.const -1 - i64.xor + i64.const -124 local.set $var0 i32.const 5 local.get $var0 struct.new $BoxedInt call $print drop - i64.const 123 - f64.convert_i64_s + f64.const 123 local.set $var1 i32.const 4 local.get $var1 struct.new $BoxedDouble call $print drop - f64.const 12.34 - f64.floor + f64.const 12 local.set $var2 i32.const 4 local.get $var2 struct.new $BoxedDouble call $print drop - f64.const 12.34 - f64.ceil + f64.const 13 local.set $var3 i32.const 4 local.get $var3 struct.new $BoxedDouble call $print drop - f64.const 12.34 - f64.trunc + f64.const 12 local.set $var4 i32.const 4 local.get $var4 Change-Id: I318d977b6a54c4028668c3626121e3cd26a7eddc Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/392122 Reviewed-by: Slava Egorov <[email protected]> Commit-Queue: Ömer Ağacan <[email protected]>
1 parent 933d630 commit 082bc3d

File tree

1 file changed

+109
-8
lines changed

1 file changed

+109
-8
lines changed

pkg/dart2wasm/lib/intrinsics.dart

Lines changed: 109 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ import 'types.dart';
1414

1515
typedef CodeGenCallback = void Function(AstCodeGenerator);
1616

17+
typedef InlineCodeGenCallback = void Function(
18+
AstCodeGenerator, Expression receiver);
19+
1720
/// Specialized code generation for external members.
1821
///
1922
/// The code is generated either inlined at the call site, or as the body of
@@ -91,8 +94,78 @@ class Intrinsifier {
9194
'truncateToDouble': (c) {
9295
c.b.f64_trunc();
9396
},
94-
'_toInt': (c) {
95-
c.b.i64_trunc_sat_f64_s();
97+
},
98+
};
99+
100+
static final Map<w.ValueType, Map<String, InlineCodeGenCallback>>
101+
_inlineUnaryOperatorMap = {
102+
intType: {
103+
'unary-': (c, receiver) {
104+
final int? intValue = _extractIntValue(receiver);
105+
if (intValue == null) {
106+
c.translateExpression(receiver, intType);
107+
c.b.i64_const(-1);
108+
c.b.i64_mul();
109+
} else {
110+
c.b.i64_const(-intValue);
111+
}
112+
},
113+
'~': (c, receiver) {
114+
final int? intValue = _extractIntValue(receiver);
115+
if (intValue == null) {
116+
c.translateExpression(receiver, intType);
117+
c.b.i64_const(-1);
118+
c.b.i64_xor();
119+
} else {
120+
c.b.i64_const(~intValue);
121+
}
122+
},
123+
'toDouble': (c, receiver) {
124+
final int? intValue = _extractIntValue(receiver);
125+
if (intValue == null) {
126+
c.translateExpression(receiver, intType);
127+
c.b.f64_convert_i64_s();
128+
} else {
129+
c.b.f64_const(intValue.toDouble());
130+
}
131+
},
132+
},
133+
doubleType: {
134+
'unary-': (c, receiver) {
135+
final double? doubleValue = _extractDoubleValue(receiver);
136+
if (doubleValue == null) {
137+
c.translateExpression(receiver, doubleType);
138+
c.b.f64_neg();
139+
} else {
140+
c.b.f64_const(-doubleValue);
141+
}
142+
},
143+
'floorToDouble': (c, receiver) {
144+
final double? doubleValue = _extractDoubleValue(receiver);
145+
if (doubleValue == null) {
146+
c.translateExpression(receiver, doubleType);
147+
c.b.f64_floor();
148+
} else {
149+
c.b.f64_const(doubleValue.floorToDouble());
150+
}
151+
},
152+
'ceilToDouble': (c, receiver) {
153+
final double? doubleValue = _extractDoubleValue(receiver);
154+
if (doubleValue == null) {
155+
c.translateExpression(receiver, doubleType);
156+
c.b.f64_ceil();
157+
} else {
158+
c.b.f64_const(doubleValue.ceilToDouble());
159+
}
160+
},
161+
'truncateToDouble': (c, receiver) {
162+
final double? doubleValue = _extractDoubleValue(receiver);
163+
if (doubleValue == null) {
164+
c.translateExpression(receiver, doubleType);
165+
c.b.f64_trunc();
166+
} else {
167+
c.b.f64_const(doubleValue.truncateToDouble());
168+
}
96169
},
97170
},
98171
};
@@ -102,7 +175,6 @@ class Intrinsifier {
102175
'floorToDouble': w.NumType.f64,
103176
'ceilToDouble': w.NumType.f64,
104177
'truncateToDouble': w.NumType.f64,
105-
'_toInt': w.NumType.i64,
106178
};
107179

108180
Translator get translator => codeGen.translator;
@@ -430,12 +502,11 @@ class Intrinsifier {
430502
} else if (node.arguments.positional.isEmpty) {
431503
// Unary operator
432504
Expression operand = node.receiver;
433-
w.ValueType opType = translator.translateType(receiverType);
434-
var code = _unaryOperatorMap[opType]?[name];
505+
w.ValueType operandType = translator.translateType(receiverType);
506+
var code = _inlineUnaryOperatorMap[operandType]?[name];
435507
if (code != null) {
436-
codeGen.translateExpression(operand, opType);
437-
code(codeGen);
438-
return _unaryResultMap[name] ?? opType;
508+
code(codeGen, operand);
509+
return _unaryResultMap[name] ?? operandType;
439510
}
440511
}
441512

@@ -1762,3 +1833,33 @@ class Intrinsifier {
17621833
return false;
17631834
}
17641835
}
1836+
1837+
int? _extractIntValue(Expression expr) {
1838+
if (expr is IntLiteral) {
1839+
return expr.value;
1840+
}
1841+
1842+
if (expr is ConstantExpression) {
1843+
final constant = expr.constant;
1844+
if (constant is IntConstant) {
1845+
return constant.value;
1846+
}
1847+
}
1848+
1849+
return null;
1850+
}
1851+
1852+
double? _extractDoubleValue(Expression expr) {
1853+
if (expr is DoubleLiteral) {
1854+
return expr.value;
1855+
}
1856+
1857+
if (expr is ConstantExpression) {
1858+
final constant = expr.constant;
1859+
if (constant is DoubleConstant) {
1860+
return constant.value;
1861+
}
1862+
}
1863+
1864+
return null;
1865+
}

0 commit comments

Comments
 (0)