Re: Counter intuitively, asserts hurt gcc static dataflow analysis.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Fri, 11 May 2018, John Carter wrote:

Here is an example where gcc's optimizers go, ahhh, strange....

There is nothing strange about it. You are trying to abuse __builtin_constant_p for warnings when it is meant for optimization. Linux kernel developers had the same issue.

Try play with the optimizations settings on godbolt.
https://godbolt.org/#g:!((g:!((g:!((h:codeEditor,i:(j:1,lang:___c,source:'%23include+%3Cstdlib.h%3E%0A%0Avoid+assertFailure(+void)+__attribute__((warning(%22Compile+time+assertion+failure%22)))%3B%0A%0Aint+z(void)%3B%0A%0A%0Aint+main()%0A%7B%0A+++int+j%3B%0A%0A+++for(++j%3D0%3Bj%3C4%3Bj%2B%2B)+%7B%0A++++++if(+z())+break%3B%0A+++%7D%0A+++%0A+++if(+__builtin_constant_p(!!(j+%3C+4)))%0A+++%7B%0A++++++if(!!(j+%3C+4))%0A+++++++++assertFailure()%3B%0A+++%7D%0A+++else%0A++++++if(+!!(j+%3C+4))%0A+++++++++abort()%3B%0A+++%0A+++return+0%3B%0A%7D%0A'),l:'5',n:'0',o:'C+source+%231',t:'0')),k:50,l:'4',n:'0',o:'',s:0,t:'0'),(g:!((h:compiler,i:(compiler:cg81,filters:(b:'0',binary:'1',commentOnly:'0',demangle:'0',directives:'0',execute:'1',intel:'0',trim:'0'),lang:___c,libs:!(),options:'-Os+-Wall',source:1),l:'5',n:'0',o:'x86-64+gcc+8.1+(Editor+%231,+Compiler+%231)+C',t:'0')),k:50,l:'4',n:'0',o:'',s:0,t:'0')),l:'2',n:'0',o:'',t:'0')),version:4

On -Os it behaves sane, on -O2 or higher it calls assertFailure.

#include <stdlib.h>

void assertFailure( void) __attribute__((warning("Compile time assertion
failure")));

int z(void);


int main()
{
  int j;

  for(  j=0;j<4;j++) {
     if( z()) break;
  }

  if( __builtin_constant_p(!(j < 4)))

gcc duplicates this piece of code, one version if we came through "break" and one version if the loop completed. For each version, the value of j<4 is known at compile-time and optimized as such. For optimization purposes, this is perfect.

  {
     if(!(j < 4))
        assertFailure();
  }
  else
     if( !(j < 4))
        abort();

  return 0;
}

--
Marc Glisse



[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux