blob: e7d1904738820684cff40ff06f80879d4a224d9b [file] [log] [blame]
// Copyright (c) 2021, 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.
// @dart = 2.7
// Tests for simplifying that we know a condition is true in the then-branch and
// false in the else-branch, and sometimes after join when a diamond exits.
/*member: check0:ConditionValue=[]*/
check0(int x) {
if (x != 1) {
return 200;
} else {
return 400;
}
}
/*member: check1:ConditionValue=[count=1&value=false&where=else,count=1&value=true&where=then]*/
check1(int x) {
if (x == 1) {
if (x == 1) return 100;
return 200;
} else {
if (x == 1) return 300;
return 400;
}
}
/*member: check2:ConditionValue=[count=1&value=false&where=then,count=1&value=true&where=else]*/
check2(int x) {
if (x != 1) {
if (x == 1) return 100;
return 200;
} else {
if (x == 1) return 300;
return 400;
}
}
/*member: check3:ConditionValue=[count=1&value=false&where=else,count=1&value=true&where=then]*/
check3(int x) {
if (x == 1) {
if (x != 1) return 100;
return 200;
} else {
if (x != 1) return 300;
return 400;
}
}
/*member: check4:ConditionValue=[count=1&value=false&where=else,count=1&value=true&where=then]*/
check4(int x) {
if (x != 1) {
if (x != 1) return 100;
return 200;
} else {
if (x != 1) return 300;
return 400;
}
}
// The first throw is in statement position, so it has an exit edge, leaving the
// rest of the method in the first branch 'else'.
/*member: join0Else:ConditionValue=[count=2&value=false&where=else]*/
join0Else(int x) {
int a = 0, b = 0, c = 0;
if (x == 1)
throw 'bad';
else
a = x + 1;
if (x == 1)
throw 'bad';
else
b = x + 2;
if (x == 1)
throw 'bad';
else
c = x + 3;
return a * b * c;
}
/*member: join1:ConditionValue=[count=2&value=false&where=else-join]*/
join1(int x) {
int a = (x == 1 ? throw 'bad' : x) + 1;
int b = (x == 1 ? throw 'bad' : x) + 2;
int c = (x == 1 ? throw 'bad' : x) + 3;
return a * b * c;
}
/*member: join2:ConditionValue=[count=2&value=true&where=then-join]*/
join2(int x) {
int a = (x == 1 ? x : throw 'bad') + 1;
int b = (x == 1 ? x : throw 'bad') + 2;
int c = (x == 1 ? x : throw 'bad') + 3;
return a * b * c;
}
/*member: join3:ConditionValue=[count=2&value=false&where=else-join]*/
join3(int x) {
int a = (x != 1 ? throw 'bad' : x) + 1;
int b = (x != 1 ? throw 'bad' : x) + 2;
int c = (x != 1 ? throw 'bad' : x) + 3;
return a * b * c;
}
/*member: join4:ConditionValue=[count=2&value=true&where=then-join]*/
join4(int x) {
int a = (x != 1 ? x : throw 'bad') + 1;
int b = (x != 1 ? x : throw 'bad') + 2;
int c = (x != 1 ? x : throw 'bad') + 3;
return a * b * c;
}
/*member: loop1:ConditionValue=[count=1&value=true&where=then]*/
loop1(int x) {
for (int i = 0; i < 10; i++) {
if (x == 1) {
sink = x == 1;
}
}
}
/*member: loop2HoistedThen:ConditionValue=[count=1&value=false&where=hoisted-then]*/
loop2HoistedThen(int x) {
// t1 = x == 1;
// t2 = !t1;
// loop:
// if (t1)
// sink = t2; // replaced with `false`.
for (int i = 0; i < 10; i++) {
if (x == 1) {
sink = x != 1;
}
}
}
/*member: loop3:ConditionValue=[count=1&value=false&where=then]*/
loop3(int x) {
for (int i = 0; i < 10; i++) {
if (x != 1) {
sink = x == 1;
}
}
}
/*member: loop4:ConditionValue=[count=1&value=true&where=then]*/
loop4(int x) {
for (int i = 0; i < 10; i++) {
if (x != 1) {
sink = x != 1;
}
}
}
/*member: loop5HoistedElseJoin:ConditionValue=[count=1&value=true&where=hoisted-else-join]*/
loop5HoistedElseJoin(int x) {
for (int i = 0; i < 10; i++) {
sink = (x == 1 ? throw 'bad' : x) + 1;
sink = x != 1;
}
}
// Unlike loop5, this is not 'hoisted'. GVN is not required to match the
// condition with its use, so the subsitution happens in a simplify pass before
// GVN/LICM can hoist the negation.
/*member: loop6ElseJoin:ConditionValue=[count=1&value=false&where=else-join]*/
loop6ElseJoin(bool x) {
for (int i = 0; i < 10; i++) {
sink = (x ? throw 'bad' : i) + 1;
sink = !x;
}
}
dynamic sink;
void main() {
check0(1);
check0(2);
check1(1);
check1(2);
check2(1);
check2(2);
check3(1);
check3(2);
check4(1);
check4(2);
join0Else(1);
join0Else(2);
join1(1);
join1(2);
join2(1);
join2(2);
join3(1);
join3(2);
join4(1);
join4(2);
loop1(1);
loop1(2);
loop2HoistedThen(1);
loop2HoistedThen(2);
loop3(1);
loop3(2);
loop4(1);
loop4(2);
loop5HoistedElseJoin(1);
loop5HoistedElseJoin(2);
loop6ElseJoin(true);
loop6ElseJoin(false);
print(sink);
}