131
|
1 /* { dg-do compile } */
|
|
2 /* { dg-options "-O3 -fdump-tree-optimized" } */
|
|
3 /* { dg-final { scan-tree-dump-not " \[/%\] " "optimized" } } */
|
|
4
|
|
5 /* Testcase submitted for PR81165, with its main function removed as
|
|
6 it's turned into a compile test. We want to make sure that all of
|
|
7 the divide/remainder computations are removed by tree optimizers.
|
|
8
|
|
9 We can figure out that we don't need to compute at runtime even the
|
|
10 condition to enter the loop: the initial i==0 would have to be
|
|
11 greater than the sum of two small unsigned values: 1U>>t1 is in the
|
|
12 range 0..1, whereas the char value is bounded by the range 0..127,
|
|
13 being 128 % a positive number (zero would invoke undefined
|
|
14 behavior, so we can assume it doesn't happen). (We know it's
|
|
15 nonnegative because it's 10 times a number that has no more than
|
|
16 the bits for 16, 8 and 1 set.)
|
|
17
|
|
18 We don't realize that the loop is useless right away: jump
|
|
19 threading helps remove some of the complexity, particularly of the
|
|
20 computation within the loop: t1 is compared with 1, but it can
|
|
21 never be 1. (We could assume as much, since its being 1 would
|
|
22 divide by zero, but we don't.)
|
|
23
|
|
24 If we don't enter the conditional block, t1 remains at 2; if we do,
|
|
25 it's set to either -1. If we jump thread at the end of the
|
|
26 conditional block, we can figure out the ranges exclude 1 and the
|
|
27 jump body is completely optimized out. However, we used to fail to
|
|
28 consider the block for jump threading due to the amount of
|
|
29 computation in it, without realizing most of it would die in
|
|
30 consequence of the threading.
|
|
31
|
|
32 We now take the dying code into account when deciding whether or
|
|
33 not to try jump threading. That might enable us to optimize the
|
|
34 function into { if (x2 != 0 || (x1 & 1) == 0) abort (); }. At the
|
|
35 time of this writing, with the patch, we get close, but the test on
|
|
36 x2 only gets as far as ((1 >> x2) == 0). Without the patch, some
|
|
37 of the loop remains. */
|
|
38
|
|
39 short x0 = 15;
|
|
40
|
|
41 void func (){
|
|
42 volatile int x1 = 1U;
|
|
43 volatile char x2 = 0;
|
|
44 char t0 = 0;
|
|
45 unsigned long t1 = 2LU;
|
|
46 int i = 0;
|
|
47
|
|
48 if(1>>x2) {
|
|
49 t0 = -1;
|
|
50 t1 = (1&(short)(x1^8U))-1;
|
|
51 }
|
|
52
|
|
53 while(i > (int)((1U>>t1)+(char)(128%(10*(25LU&(29%x0)))))) {
|
|
54 i += (int)(12L/(1!=(int)t1));
|
|
55 }
|
|
56
|
|
57 if (t0 != -1) __builtin_abort();
|
|
58 if (t1 != 0L) __builtin_abort();
|
|
59 }
|