Fix the output type of HNegate.

TBR=sigmund@google.com

Change-Id: If5875aac80f111bb95852ad4d9f568dadf4f9d65
Reviewed-on: https://dart-review.googlesource.com/51980
Reviewed-by: Stephen Adams <sra@google.com>
Reviewed-by: Sigmund Cherem <sigmund@google.com>
Commit-Queue: Stephen Adams <sra@google.com>
This commit is contained in:
Stephen Adams
2018-04-19 20:18:38 +00:00
committed by commit-bot@chromium.org
parent 2f9f8088b5
commit 32df3387f2
2 changed files with 64 additions and 3 deletions
@@ -248,8 +248,18 @@ class UnaryNegateSpecializer extends InvokeDynamicSpecializer {
GlobalTypeInferenceResults results,
CompilerOptions options,
ClosedWorld closedWorld) {
TypeMask operandType = instruction.inputs[1].instructionType;
if (instruction.inputs[1].isNumberOrNull(closedWorld)) return operandType;
HInstruction operand = instruction.inputs[1];
if (operand.isNumberOrNull(closedWorld)) {
// We have integer subclasses that represent ranges, so widen any int
// subclass to full integer.
if (operand.isIntegerOrNull(closedWorld)) {
return closedWorld.commonMasks.intType;
}
if (operand.isDoubleOrNull(closedWorld)) {
return closedWorld.commonMasks.doubleType;
}
return closedWorld.commonMasks.numType;
}
return super
.computeTypeFromInputTypes(instruction, results, options, closedWorld);
}
@@ -263,7 +273,11 @@ class UnaryNegateSpecializer extends InvokeDynamicSpecializer {
ClosedWorld closedWorld) {
HInstruction input = instruction.inputs[1];
if (input.isNumber(closedWorld)) {
return new HNegate(input, instruction.selector, input.instructionType);
return new HNegate(
input,
instruction.selector,
computeTypeFromInputTypes(
instruction, results, options, closedWorld));
}
return null;
}
@@ -0,0 +1,47 @@
// Copyright (c) 2018, 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.
import 'package:async_helper/async_helper.dart';
import '../compiler_helper.dart';
// A bug in UnaryNegateSpecializer left '-a' labelled as 'positive', allowing
// misoptimization of '<<'.
const String TEST1 = r"""
foo(param) {
var a = param ? 0xFFFFFFFF : 1;
return 1 << -a;
// present: '$shl'
// absent: '_shlPositive'
}
""";
const String TEST2 = r"""
foo(param) {
var a = param ? 0xFFFFFFFF : 1;
return 1 << a;
// present: '_shlPositive'
// absent: '$shl'
}
""";
main() {
runTests({bool useKernel}) async {
check(String test) async {
await compile(test,
entry: 'foo',
useKernel: useKernel,
check: checkerForAbsentPresent(test));
}
await check(TEST1);
await check(TEST2);
}
asyncTest(() async {
print('--test from ast---------------------------------------------------');
await runTests(useKernel: false);
print('--test from kernel------------------------------------------------');
await runTests(useKernel: true);
});
}