| /* { 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(); |

| } |