[llvm-dev] Proposed new min and max intrinsics

Fabian Giesen via llvm-dev llvm-dev at lists.llvm.org
Thu Nov 8 20:35:52 PST 2018


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.

-Fabian

On 11/7/2018 8:12 PM, Thomas Lively via llvm-dev wrote:
> Alex,
> 
> After looking into this a bit, it looks to me like the best thing to do 
> for targets that do not natively support ISD::MINIMUM and ISD::MAXIMUM 
> would be to fall back to a libcall, since implementing these operations 
> in terms of existing operations is actually rather complicated. Do you 
> think it would make sense to add builtin functions to compiler-rt to 
> implement these operations, or is there a better way of handling this?
> 
> Thanks,
> 
> Thomas
> 
> On Thu, Nov 1, 2018 at 11:49 AM Thomas Lively <tlively at google.com 
> <mailto:tlively at google.com>> wrote:
> 
>     Sounds good, I'll take a look.
> 
>     On Thu, Nov 1, 2018 at 9:45 AM Alex Bradbury <asb at asbradbury.org
>     <mailto:asb at asbradbury.org>> wrote:
> 
>         On Thu, 11 Oct 2018 at 00:28, Thomas Lively via llvm-dev
>         <llvm-dev at lists.llvm.org <mailto:llvm-dev at lists.llvm.org>> wrote:
>          >
>          > I just wanted to bump this to see if anyone has any input. I
>         would really like to get these landed soon if there are no
>         objections.
> 
>         Hi Thomas,
> 
>         With ISD::FMINNAN and ISD::FMAXNAN now easy to produce for any
>         target
>         due to these newly exposed intrinsics, I think these nodes should be
>         handled in at least SelectionDAGLegalize::ExpandNode (for when the
>         float type is legal but the operation is not) and
>         DAGTypeLegalizer::SoftenFloatResult (for when the float type is not
>         legal).
> 
>         Best,
> 
>         Alex
> 
> 
> 
> _______________________________________________
> LLVM Developers mailing list
> llvm-dev at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
> 


More information about the llvm-dev mailing list