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