[llvm-dev] Side-channel resistant values

David Zarzycki via llvm-dev
2019-09-14T06:12:29Z

Hi Chandler,

I feel like this conversation has come full circle. So to ask again: how does
one force CMOV to be emitted? You suggested “__builtin_unpredictable()” but that
gets lost in various optimization passes. Given other architectures have CMOV
like instructions, and given the usefulness of the instruction for performance
tuning, it seems like a direct intrinsic would be best. What am I missing?

Dave

> On Sep 14, 2019, at 8:35 AM, Chandler Carruth <chandlerc at
gmail.com> wrote:
>
> ﻿
> The x86 backend is extremely aggressive in turning cmov with memory
operands into branches because that is often faster even for poorly predicted
branches due to the forced stall in the cmov.
>
>> On Fri, Sep 13, 2019 at 11:19 PM David Zarzycki <dave at znu.io>
wrote:
>> I’m struggling to find cases where __builtin_unpredictable() works at
all. Even if we ignore cmp/br into switch conversion, it still doesn’t work:
>>
>> int test_cmov(int left, int right, int *alt) {
>>         return __builtin_unpredictable(left < right) ? *alt : 999;
>> }
>>
>> Should generate:
>>
>> test_cmov:
>>         movl    $999, %eax
>>         cmpl    %esi, %edi
>>         cmovll  (%rdx), %eax
>>         retq
>>
>> But currently generates:
>>
>> test_cmov:
>>         movl    $999, %eax
>>         cmpl    %esi, %edi
>>         jge     .LBB0_2
>>         movl    (%rdx), %eax
>> .LBB0_2:
>>         retq
>>
>>
>>
>> > On Sep 14, 2019, at 12:18 AM, Sanjay Patel <spatel at
rotateright.com> wrote:
>> >
>> > I'm not sure if this is the entire problem, but SimplifyCFG
loses the 'unpredictable' metadata when it converts a set of cmp/br into
a switch:
>> > https://godbolt.org/z/neLzN3
>> >
>> > Filed here:
>> > https://bugs.llvm.org/show_bug.cgi?id=43313
>> >
>> > On Fri, Sep 13, 2019 at 4:02 AM David Zarzycki via llvm-dev
<llvm-dev at lists.llvm.org> wrote:
>> >
>> >
>> >> On Sep 13, 2019, at 10:45 AM, Chandler Carruth <chandlerc
at gmail.com> wrote:
>> >>
>> >> On Fri, Sep 13, 2019 at 1:33 AM David Zarzycki via llvm-dev
<llvm-dev at lists.llvm.org> wrote:
>> >> Hi Chandler,
>> >>
>> >> The data-invariant feature sounds great but what about the
general case? When performance tuning code, people sometimes need the ability to
reliably generate CMOV, and right now the best advice is either “use inline
assembly” or “keep refactoring until CMOV is emited” (and hope that future
compilers continue to generate CMOV).
>> >>
>> >> Given that a patch already exists to reliably generate CMOV,
are there any good arguments against adding the feature?
>> >>
>> >> For *performance* tuning, the builtin that Hal mentioned is
IMO the correct design.
>> >>
>> >> Is there some reason why it doesn't work?
>> >
>> > I wasn’t aware of __builtin_unpredictable() until now and I
haven’t debugged why it doesn’t work, but here are a couple examples, one using
the ternary operator and one using a switch statement:
>> >
>> > https://godbolt.org/z/S46I_q
>> >
>> > Dave
>> > _______________________________________________
>> > LLVM Developers mailing list
>> > llvm-dev at lists.llvm.org
>> > https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
<http://lists.llvm.org/pipermail/llvm-dev/attachments/20190914/661856f0/attachment.html>