view gcc/testsuite/gcc.dg/pr81165.c @ 145:1830386684a0

gcc-9.2.0
author anatofuz
date Thu, 13 Feb 2020 11:34:05 +0900
parents 84e7813d76e9
children
line wrap: on
line source

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