mirror of
https://github.com/autc04/Retro68.git
synced 2024-09-28 03:55:14 +00:00
60 lines
2.3 KiB
C
60 lines
2.3 KiB
C
/* { dg-do compile } */
|
|
/* { dg-options "-O3 -fdump-tree-optimized" } */
|
|
/* { dg-final { scan-tree-dump-not " \[/%\] " "optimized" } } */
|
|
|
|
/* Testcase submitted for PR81165, with its main function removed as
|
|
it's turned into a compile test. We want to make sure that all of
|
|
the divide/remainder computations are removed by tree optimizers.
|
|
|
|
We can figure out that we don't need to compute at runtime even the
|
|
condition to enter the loop: the initial i==0 would have to be
|
|
greater than the sum of two small unsigned values: 1U>>t1 is in the
|
|
range 0..1, whereas the char value is bounded by the range 0..127,
|
|
being 128 % a positive number (zero would invoke undefined
|
|
behavior, so we can assume it doesn't happen). (We know it's
|
|
nonnegative because it's 10 times a number that has no more than
|
|
the bits for 16, 8 and 1 set.)
|
|
|
|
We don't realize that the loop is useless right away: jump
|
|
threading helps remove some of the complexity, particularly of the
|
|
computation within the loop: t1 is compared with 1, but it can
|
|
never be 1. (We could assume as much, since its being 1 would
|
|
divide by zero, but we don't.)
|
|
|
|
If we don't enter the conditional block, t1 remains at 2; if we do,
|
|
it's set to either -1. If we jump thread at the end of the
|
|
conditional block, we can figure out the ranges exclude 1 and the
|
|
jump body is completely optimized out. However, we used to fail to
|
|
consider the block for jump threading due to the amount of
|
|
computation in it, without realizing most of it would die in
|
|
consequence of the threading.
|
|
|
|
We now take the dying code into account when deciding whether or
|
|
not to try jump threading. That might enable us to optimize the
|
|
function into { if (x2 != 0 || (x1 & 1) == 0) abort (); }. At the
|
|
time of this writing, with the patch, we get close, but the test on
|
|
x2 only gets as far as ((1 >> x2) == 0). Without the patch, some
|
|
of the loop remains. */
|
|
|
|
short x0 = 15;
|
|
|
|
void func (){
|
|
volatile int x1 = 1U;
|
|
volatile char x2 = 0;
|
|
char t0 = 0;
|
|
unsigned long t1 = 2LU;
|
|
int i = 0;
|
|
|
|
if(1>>x2) {
|
|
t0 = -1;
|
|
t1 = (1&(short)(x1^8U))-1;
|
|
}
|
|
|
|
while(i > (int)((1U>>t1)+(char)(128%(10*(25LU&(29%x0)))))) {
|
|
i += (int)(12L/(1!=(int)t1));
|
|
}
|
|
|
|
if (t0 != -1) __builtin_abort();
|
|
if (t1 != 0L) __builtin_abort();
|
|
}
|