blob: b41f3b7f4cf40a2e6eb903508b9d4c1f0ae78ac2 [file] [log] [blame]
// Copyright (c) 2017, 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.
// Regression test for dartbug.com/29620: check that decision to deoptimize
// and decisions which parts of the instruction to emit use the same
// range information for instruction inputs.
// VMOptions=--optimization_counter_threshold=10 --no-use-osr --no-background-compilation
import "package:expect/expect.dart";
class Flag {
var value;
Flag(this.value);
static final FLAG = new Flag(0);
}
@pragma('vm:prefer-inline')
void checkRange(bit) {
if (bit < 0 || bit > 31) {
throw "bit must be in [0, 31]";
}
}
@pragma('vm:prefer-inline')
bool isSet(flags, bit) {
checkRange(bit);
// Note: > 0 here instead of == 0 to prevent merging into
// TestSmi instruction.
return (flags & (1 << bit)) > 0;
}
@pragma('vm:never-inline')
bool bug(flags) {
var bit = Flag.FLAG.value;
checkRange(bit);
for (var i = 0; i < 1; i++) {
bit = Flag.FLAG.value;
checkRange(bit);
}
// In early optimization stages `bit` would be a Phi(...). This Phi would be
// dominated by checkRange and thus range analysis will infer [0, 31] range
// for it - and thus a EliminateEnvironment will make decision that
// (1 << bit) can't deoptimize and will detach environment from it. Later
// passes will eliminate Phi for `bit` as it is redundant and as a result we
// will loose precise range information for `bit` and backend will try
// to emit a range check and a deoptimization.
return isSet(flags, bit);
}
main() {
for (var i = 0; i < 100; i++) {
bug(1);
}
}