| /* See backwards thru casts if the range fits the LHS type. */ |
| /* { dg-do compile } */ |
| /* { dg-options "-O2 -fdump-tree-evrp" } */ |
| |
| extern void kill(int i); |
| extern void keep(int i); |
| |
| void |
| foo (int i) |
| { |
| if (i >= 10) |
| { |
| if (i <= 100) |
| { |
| /* i has a range of [10, 100] */ |
| char c = (char) i; |
| if (c < 30) |
| { |
| /* If we wind back thru the cast with the range of c being [10,29] |
| * from the branch, and recognize that the range of i fits within |
| * a cast to c, then there is no missing information in a cast |
| * back to int. We can use the range calculated for 'c' with 'i' |
| * as well and Ranger should be able to kill the call. */ |
| if (i > 29) |
| kill (i); |
| } |
| } |
| /* i has a range of [10, MAX] */ |
| char d = (char) i; |
| if (d < 30) |
| { |
| /* Here, a cast to a char and back is NOT equivalent, so we cannot use |
| * the value of d to remove the call. */ |
| if (i > 29) |
| keep (i); |
| } |
| |
| } |
| } |
| |
| /* { dg-final { scan-tree-dump-times "kill \\(" 0 "evrp"} } */ |
| /* { dg-final { scan-tree-dump-times "keep \\(" 1 "evrp"} } */ |
| |