[llvm-dev] Proposed new min and max intrinsics

Thomas Lively via llvm-dev llvm-dev at lists.llvm.org
Fri Nov 9 10:56:36 PST 2018


I would agree, but the expansion also has to properly treat negative zero
as less than zero, which leads to something like the following:

;; Find minimum if both zero
%a_sign = fgetsign %a
%b_sign = fgetsign %b
%a_is_lesser_zero = icmp ugt %a_sign, %b_sign
%minimum_zeros = select %a_is_lesser_zero, %a, %b

;; Find minimum if not both zero (from above)
%no_nan_and_a_lesser = fcmp olt %a, %b
%lesser_or_b_if_nan = select %no_nan_and_a_lesser, %a, %b
%a_not_nan = fcmp ord %a, %a
%minimum_not_zeros = select %a_not_nan, %lesser_or_b_if_nan, %a

;; Choose between zeros and not-zeros
%a_is_zero = fcmp oeq %a, 0
%b_is_zero = fcmp oeq %b, 0
%both_zero = and %a_is_zero, %b_is_zero
%minimum = select %both_zero, %minimum_zeros, %minimum_not_zeros

Which is considerably less reasonable.



On Fri, Nov 9, 2018 at 7:00 AM Cameron McInally via llvm-dev <
llvm-dev at lists.llvm.org> wrote:

> On Thu, Nov 8, 2018 at 11:35 PM Fabian Giesen via llvm-dev <
> llvm-dev at lists.llvm.org> wrote:
>
>> What is so complicated about these? Shouldn't they just correspond to
>> two compares + selects?
>>
>> To give a concrete example, x86 MIN[SP][SD] and MAX[SP][SD],
>> respectively, correspond exactly to
>>
>>    MIN*: select(a < b, a, b) (i.e. "a < b ? a : b")
>>    MAX*: select(a > b, a, b) (i.e. "a > b ? a : b")
>>
>> IIRC, MINIMUM and MAXIMUM have the added requirement that they should
>> return NaN if _either_ input is NaN, whereas the above will return NaN
>> if the second input (i.e. b) is NaN, but not if the first is.
>>
>> So we need to explicitly catch the case where a is NaN as well. For
>> minimum, that works out to something like:
>>
>>    %3 = fcmp olt float %a, %b
>>    %4 = select i1 %3, float %a, float %b ; (a < b) ? a : b
>>    %5 = fcmp ord float %a, %a ; true if !isNaN(a)
>>    %6 = select i1 %5, float %4, float %a ; if a was NaN, return a
>>
>> for the entire operation. The logic here is that if isNaN(a) ||
>> isNaN(b), the initial comparison will evaluate to false and %4 ends up
>> being b. If isNaN(b), this is a NaN value (as required). The case we are
>> missing is when isNaN(a) && !isNaN(b), where %4 is not a NaN; the second
>> compare + select fixes that one up.
>>
>> The first pair of these corresponds to a single (x86-style) MIN/MAX, and
>> the second turns into a compare followed by (depending on target
>> instruction set) either a BLEND or some logic ops.
>>
>> For minimumNumber/maximumNumber, you should be able to use a similar
>> construction. Showing the example for minimumNumber here:
>>
>>    %3 = fcmp olt float %a, %b
>>    %4 = select i1 %3, float %a, float %b ; (a < b) ? a : b
>>    %5 = fcmp ord float %b, %b ; true if !isNaN(b)
>>    %6 = select i1 %5, float %4, float %a ; if b was NaN, return a
>>
>> Starts out the same as before. Here, the tricky case is !isNaN(a) &&
>> isNaN(b). The initial select %4 will result in the (NaN) b in that case,
>> and the second compare/select pair switches the result to a instead; we
>> will only get a NaN result if both inputs were NaN.
>>
>> I might be missing something here, but that seems like a fairly harmless
>> expansion, as such things go, and going to compiler-rt feels like
>> overkill.
>>
>
> +1
> _______________________________________________
> LLVM Developers mailing list
> llvm-dev at lists.llvm.org
> http://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/20181109/8babe0fb/attachment.html>


More information about the llvm-dev mailing list