Index: pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart |
diff --git a/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart b/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart |
index 7f5ff1d584fcc09a01da15778c627a2e97d30d11..c8cfebc91b45293457c033c1b59d729945acb2be 100644 |
--- a/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart |
+++ b/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart |
@@ -223,11 +223,16 @@ abstract class BinaryArithmeticSpecializer extends InvokeDynamicSpecializer { |
bool inputsArePositiveIntegers(HInstruction instruction, Compiler compiler) { |
HInstruction left = instruction.inputs[1]; |
HInstruction right = instruction.inputs[2]; |
- JavaScriptBackend backend = compiler.backend; |
return left.isPositiveIntegerOrNull(compiler) |
&& right.isPositiveIntegerOrNull(compiler); |
} |
+ bool inputsAreUInt31(HInstruction instruction, Compiler compiler) { |
+ HInstruction left = instruction.inputs[1]; |
+ HInstruction right = instruction.inputs[2]; |
+ return left.isUInt31(compiler) && right.isUInt31(compiler); |
+ } |
+ |
HInstruction newBuiltinVariant(HInvokeDynamic instruction, Compiler compiler); |
Selector renameToOptimizedSelector(String name, |
@@ -249,6 +254,10 @@ class AddSpecializer extends BinaryArithmeticSpecializer { |
TypeMask computeTypeFromInputTypes(HInvokeDynamic instruction, |
Compiler compiler) { |
+ if (inputsAreUInt31(instruction, compiler)) { |
+ JavaScriptBackend backend = compiler.backend; |
+ return backend.uint32Type; |
+ } |
if (inputsArePositiveIntegers(instruction, compiler)) { |
JavaScriptBackend backend = compiler.backend; |
return backend.positiveIntType; |
@@ -313,6 +322,7 @@ class ModuloSpecializer extends BinaryArithmeticSpecializer { |
HInstruction newBuiltinVariant(HInvokeDynamic instruction, |
Compiler compiler) { |
// Modulo cannot be mapped to the native operator (different semantics). |
+ // TODO(sra): For non-negative values we can use JavaScript's %. |
return null; |
} |
} |
@@ -365,8 +375,11 @@ class TruncatingDivideSpecializer extends BinaryArithmeticSpecializer { |
TypeMask computeTypeFromInputTypes(HInvokeDynamic instruction, |
Compiler compiler) { |
+ JavaScriptBackend backend = compiler.backend; |
+ if (hasUint31Result(instruction, compiler)) { |
+ return backend.uint31Type; |
+ } |
if (inputsArePositiveIntegers(instruction, compiler)) { |
- JavaScriptBackend backend = compiler.backend; |
return backend.positiveIntType; |
} |
return super.computeTypeFromInputTypes(instruction, compiler); |
@@ -380,13 +393,35 @@ class TruncatingDivideSpecializer extends BinaryArithmeticSpecializer { |
return count != 0; |
} |
+ bool isTwoOrGreater(HInstruction instruction, Compiler compiler) { |
+ if (!instruction.isConstantInteger()) return false; |
+ HConstant rightConstant = instruction; |
+ IntConstantValue intConstant = rightConstant.constant; |
+ int count = intConstant.primitiveValue; |
+ return count >= 2; |
+ } |
+ |
+ bool hasUint31Result(HInstruction instruction, Compiler compiler) { |
+ HInstruction left = instruction.inputs[1]; |
+ HInstruction right = instruction.inputs[2]; |
+ if (right.isPositiveInteger(compiler)) { |
+ if (left.isUInt31(compiler) && isNotZero(right, compiler)) { |
+ return true; |
+ } |
+ if (left.isUInt32(compiler) && isTwoOrGreater(right, compiler)) { |
+ return true; |
+ } |
+ } |
+ return false; |
+ } |
+ |
HInstruction tryConvertToBuiltin(HInvokeDynamic instruction, |
Compiler compiler) { |
HInstruction left = instruction.inputs[1]; |
HInstruction right = instruction.inputs[2]; |
if (isBuiltin(instruction, compiler)) { |
if (right.isPositiveInteger(compiler) && isNotZero(right, compiler)) { |
- if (left.isUInt31(compiler)) { |
+ if (hasUint31Result(instruction, compiler)) { |
return newBuiltinVariant(instruction, compiler); |
} |
// We can call _tdivFast because the rhs is a 32bit integer |