Index: pkg/compiler/lib/src/cps_ir/type_propagation.dart |
diff --git a/pkg/compiler/lib/src/cps_ir/type_propagation.dart b/pkg/compiler/lib/src/cps_ir/type_propagation.dart |
index f45de41c118b18a988863d9b17a9cfa16c14ee66..f0aae40fc04a1a2be6b51937d9f9a0e6ef707f3e 100644 |
--- a/pkg/compiler/lib/src/cps_ir/type_propagation.dart |
+++ b/pkg/compiler/lib/src/cps_ir/type_propagation.dart |
@@ -243,8 +243,15 @@ class ConstantPropagationLattice { |
/// |
/// This method returns `null` if a good result could not be found. In that |
/// case, it is best to fall back on interprocedural type information. |
- AbstractValue unaryOp(UnaryOperator operator, |
- AbstractValue value) { |
+ AbstractValue unaryOp(UnaryOperator operator, AbstractValue value) { |
+ switch (operator.kind) { |
+ case UnaryOperatorKind.COMPLEMENT: |
+ return bitNotSpecial(value); |
+ case UnaryOperatorKind.NEGATE: |
+ return negateSpecial(value); |
+ default: |
+ break; |
+ } |
// TODO(asgerf): Also return information about whether this can throw? |
if (value.isNothing) { |
return nothing; |
@@ -334,6 +341,27 @@ class ConstantPropagationLattice { |
return null; // The caller will use return type from type inference. |
} |
+ AbstractValue foldUnary(UnaryOperation operation, AbstractValue value) { |
+ if (value.isNothing) return nothing; |
+ if (value.isConstant) { |
+ ConstantValue result = operation.fold(value.constant); |
+ if (result != null) return constant(result); |
+ } |
+ return null; |
+ } |
+ |
+ AbstractValue bitNotSpecial(AbstractValue value) { |
+ return foldUnary(constantSystem.bitNot, value); |
+ } |
+ |
+ AbstractValue negateSpecial(AbstractValue value) { |
+ AbstractValue folded = foldUnary(constantSystem.negate, value); |
+ if (folded != null) return folded; |
+ if (isDefinitelyInt(value)) return nonConstant(typeSystem.intType); |
+ return null; |
+ } |
+ |
+ |
AbstractValue foldBinary(BinaryOperation operation, |
AbstractValue left, AbstractValue right) { |
if (left.isNothing || right.isNothing) return nothing; |
@@ -492,7 +520,6 @@ class ConstantPropagationLattice { |
return foldBinary(constantSystem.greaterEqual, left, right); |
} |
- |
AbstractValue stringConstant(String value) { |
return constant(new StringConstantValue(new ast.DartString.literal(value))); |
} |
@@ -938,17 +965,24 @@ class TransformingVisitor extends DeepRecursiveVisitor { |
/// Returns `true` if the node was replaced. |
bool specializeOperatorCall(InvokeMethod node) { |
Continuation cont = node.continuation.definition; |
- bool replaceWithBinary(BuiltinOperator operator, |
- Primitive left, |
- Primitive right) { |
- Primitive prim = |
- new ApplyBuiltinOperator(operator, <Primitive>[left, right], |
- node.sourceInformation); |
+ bool replaceWithPrimitive(Primitive prim) { |
LetPrim let = makeLetPrimInvoke(prim, cont); |
replaceSubtree(node, let); |
push(let); |
return true; // So returning early is more convenient. |
} |
+ bool replaceWithBinary(BuiltinOperator operator, |
+ Primitive left, |
+ Primitive right) { |
+ return replaceWithPrimitive( |
+ new ApplyBuiltinOperator( |
+ operator, <Primitive>[left, right], node.sourceInformation)); |
+ } |
+ bool replaceWithUnary(BuiltinOperator operator, Primitive argument) { |
+ return replaceWithPrimitive( |
+ new ApplyBuiltinOperator( |
+ operator, <Primitive>[argument], node.sourceInformation)); |
+ } |
if (node.selector.isOperator && node.arguments.length == 2) { |
Primitive leftArg = getDartReceiver(node); |
@@ -1032,6 +1066,20 @@ class TransformingVisitor extends DeepRecursiveVisitor { |
} |
} |
} |
+ if (node.selector.isOperator && node.arguments.length == 1) { |
+ Primitive argument = getDartReceiver(node); |
+ AbstractValue value = getValue(argument); |
+ |
+ if (lattice.isDefinitelyNum(value, allowNull: false)) { |
+ String opname = node.selector.name; |
+ if (opname == '~') { |
+ return replaceWithUnary(BuiltinOperator.NumBitNot, argument); |
+ } |
+ if (opname == 'unary-') { |
+ return replaceWithUnary(BuiltinOperator.NumNegate, argument); |
+ } |
+ } |
+ } |
if (node.selector.isCall) { |
String name = node.selector.name; |
Primitive receiver = getDartReceiver(node); |
@@ -2508,6 +2556,12 @@ class TypePropagationVisitor implements Visitor { |
void visitApplyBuiltinOperator(ApplyBuiltinOperator node) { |
+ void unaryOp(AbstractValue operation(AbstractValue argument), |
+ TypeMask defaultType) { |
+ AbstractValue value = getValue(node.arguments[0].definition); |
+ setValue(node, operation(value) ?? nonConstant(defaultType)); |
+ } |
+ |
void binaryOp( |
AbstractValue operation(AbstractValue left, AbstractValue right), |
TypeMask defaultType) { |
@@ -2649,6 +2703,14 @@ class TypePropagationVisitor implements Visitor { |
binaryBoolOp(lattice.greaterEqualSpecial); |
break; |
+ case BuiltinOperator.NumBitNot: |
+ unaryOp(lattice.bitNotSpecial, typeSystem.uint32Type); |
+ break; |
+ |
+ case BuiltinOperator.NumNegate: |
+ unaryOp(lattice.negateSpecial, typeSystem.numType); |
+ break; |
+ |
case BuiltinOperator.StrictNeq: |
case BuiltinOperator.LooseNeq: |
case BuiltinOperator.IsFalsy: |