Optimization breaks inline asm code w/ptrs

Andrew Pinski pinskia@gmail.com
Sun Aug 13 05:40:00 GMT 2017


On Sat, Aug 12, 2017 at 10:08 PM, Andrew Pinski <pinskia@gmail.com> wrote:
> On Sat, Aug 12, 2017 at 9:21 PM, David Wohlferd <dw@limegreensocks.com> wrote:
>> Environment:
>> gcc 6.1
>> compiling for 64bit i386
>> optimizations: -O2
>>
>> Consider this simple bit of code (from
>> https://stackoverflow.com/a/45656087/2189500):
>>
>> #include <stdio.h>
>>
>> int getStringLength(const char *pStr){
>>
>>     int len;
>>
>>     __asm__  (
>>         "repne scasb\n\t"
>>         "not %%ecx\n\t"
>>         "dec %%ecx"
>>         :"=c" (len), "+D"(pStr)
>>         :"c"(-1), "a"(0)
>>     );
>>
>>     return len;
>> }
>>
>> int main()
>> {
>>    char buff[50] = "hello world";
>>    int a = getStringLength(buff);
>>    printf("%s: %d\n", buff, a);
>> }
>>
>> This code works as expected and prints out 11.  Yay.
>>
>> However, if you add "buff[4] = 0;" before the call to getStringLength, it
>> STILL prints out 11 (when optimizations are enabled), when it should print
>> 4.
>>
>> I would expect this kind of behavior if the asm were in 'main.' But it has
>> always been my understanding that function calls performed an implicit
>> memory clobber.  The fact that this clobber goes away during inlining means
>> that code can stop working any time the compiler makes a different decision
>> about whether or not to inline a function.  Ouch.
>>
>> And before somebody asks:  Adding "+m"(pStr) does not help.
>
> But does adding:
> "+m"(*pStr)
>
> Help?
>
>
> "+m"(pStr)  Just says pStr variable changes, not what it points to.


I should ask why are you using inline-asm for this?  strlen will have
the best optimized version for your processor anyways.

Thanks,
Andrew

> Thanks,
> Andrew Pinski
>
>>
>> The result is that (apparently) you can NEVER safely pass a buffer pointer
>> to inline asm without using the memory clobber.  If this is true, I don't
>> believe it is widely known.
>>
>> Given how 'heavy' memory clobbers are, I would hope that only pointers that
>> have 'escaped' the function would get flushed before a function call.  But
>> not flushing *anything* seems very bad.
>>
>> dw
>>



More information about the Gcc mailing list