Thomas Lively via llvm-dev
2018-Nov-08 04:12 UTC
[llvm-dev] Proposed new min and max intrinsics
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> wrote:> Sounds good, I'll take a look. > > On Thu, Nov 1, 2018 at 9:45 AM Alex Bradbury <asb at asbradbury.org> wrote: > >> On Thu, 11 Oct 2018 at 00:28, Thomas Lively via llvm-dev >> <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 >> >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20181107/a3bc8898/attachment.html>
Fabian Giesen via llvm-dev
2018-Nov-09 04:35 UTC
[llvm-dev] Proposed new min and max intrinsics
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 >
Cameron McInally via llvm-dev
2018-Nov-09 15:00 UTC
[llvm-dev] Proposed new min and max intrinsics
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 -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20181109/3bf0c105/attachment.html>