This is the mail archive of the gcc-help@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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


Here's a variant that works even at  -O3, the trick seems to be to combine
__builtin_choose_expr with __builtin_constant_p

https://godbolt.org/g/pQeRvE

#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;
   }

   __builtin_choose_expr( __builtin_constant_p(!(j < 4)),
                          ((!(j < 4)) ? assertFailure() : (void)0),
                          ((!(j < 4)) ? abort() : (void)0));

   return 0;
}


On Fri, May 11, 2018 at 10:37 AM, Marc Glisse <marc.glisse@inria.fr> wrote:

> 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+assertFail
>> ure(+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
>



-- 
John Carter
Phone : (64)(3) 358 6639
Tait Electronics
PO Box 1645 Christchurch
New Zealand

-- 
This Communication is Confidential. We only send and receive email on the

basis of the terms set out at www.taitradio.com/email_disclaimer 
<http://www.taitradio.com/email_disclaimer>


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]