Hi, I’d like to re-propose adding intrinsics for fmin / fmax. These can be used to implement the equivalent libm functions as defined in C99 and OpenCL, which R600 and AArch64 at least have instructions with the same semantics. This is not equivalent to a simple fcmp + select due to its handling of NaNs. This has been proposed before, but never delivered (http://lists.cs.uiuc.edu/pipermail/llvmdev/2012-December/057128.html) To summarize: 1. If either operand is a NaN, returns the other operand 2. If both operands are NaN, returns NaN 3. If the operands are equal, returns a value that will compare equal to both arguments 4. In the normal case, returns the smaller / larger operand 5. Ignore what to do for signaling NaNs, since that’s what the rest of LLVM does currently anyway - Handling of fmin/fmax (+/- 0.0, +/- 0.0) Point 3 is worded as such because this doesn’t seem particularly well specified by any standard I’ve looked at. The most explicit mention of this I’ve found is a footnote in C99 that “Ideally, fmax would be sensitive to the sign of zero, for example fmax(-0.0, 0.0) would return +0; however, implementation in software might be impractical.” It doesn’t really state what the expected behavior is. glibc and OS X’s libc disagree on the (+0, -0) and (-0, +0) cases. To resolve this, the semantics of the intrinsic will be that either will be OK as long as the result compares equal. For the purposes of constant folding, I’ve tried to follow the literal wording which was most explicit for the expected result from OpenCL (http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/fmin.html) and taking the comparison +/-0.0 < +/-0.0 will fail. This means the constant folded results will be: fmin(0.0, 0.0) = 0.0 fmin(0.0, -0.0) = 0.0 fmin(-0.0, 0.0) = -0.0 fmin(-0.0, -0.0) = -0.0 Other options would be to always use +0.0, or to be sensitive to the sign and claim -0.0 is less than 0.0. -------------- next part -------------- A non-text attachment was scrubbed... Name: 0001-Add-fmin-fmax-intrinsics.patch Type: application/octet-stream Size: 84229 bytes Desc: not available URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20140813/2b43526b/attachment.obj> -------------- next part -------------- A non-text attachment was scrubbed... Name: 0002-Add-basic-fmin-fmax-instcombines.patch Type: application/octet-stream Size: 8386 bytes Desc: not available URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20140813/2b43526b/attachment-0001.obj> -------------- next part -------------- A non-text attachment was scrubbed... Name: 0003-Fold-fmin-fmax-with-infinities.patch Type: application/octet-stream Size: 4096 bytes Desc: not available URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20140813/2b43526b/attachment-0002.obj> -------------- next part -------------- A non-text attachment was scrubbed... Name: 0004-Move-fmin-fmax-constant-folding-logic-into-APFloat.patch Type: application/octet-stream Size: 4061 bytes Desc: not available URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20140813/2b43526b/attachment-0003.obj>
I have no position on whether or not these should be added, but if they are they should match the IEEE 754 semantics, which fully specify all of these details. (Signaling NaNs could still be left unspecified as they're optional in IEEE-754). - Steve Sent from my iPhone> On Aug 13, 2014, at 7:38 PM, Matt Arsenault <arsenm2 at gmail.com> wrote: > > Hi, > > I’d like to re-propose adding intrinsics for fmin / fmax. These can be used to implement the equivalent libm functions as defined in C99 and OpenCL, which R600 and AArch64 at least have instructions with the same semantics. This is not equivalent to a simple fcmp + select due to its handling of NaNs. > > This has been proposed before, but never delivered (http://lists.cs.uiuc.edu/pipermail/llvmdev/2012-December/057128.html) > > To summarize: > 1. If either operand is a NaN, returns the other operand > 2. If both operands are NaN, returns NaN > 3. If the operands are equal, returns a value that will compare equal to both arguments > 4. In the normal case, returns the smaller / larger operand > 5. Ignore what to do for signaling NaNs, since that’s what the rest of LLVM does currently anyway > > - Handling of fmin/fmax (+/- 0.0, +/- 0.0) > Point 3 is worded as such because this doesn’t seem particularly well specified by any standard I’ve looked at. The most explicit mention of this I’ve found is a footnote in C99 that “Ideally, fmax would be sensitive to the sign of zero, for example fmax(-0.0, 0.0) would return +0; however, implementation in software might be impractical.” It doesn’t really state what the expected behavior is. glibc and OS X’s libc disagree on the (+0, -0) and (-0, +0) cases. To resolve this, the semantics of the intrinsic will be that either will be OK as long as the result compares equal. > > For the purposes of constant folding, I’ve tried to follow the literal wording which was most explicit for the expected result from OpenCL (http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/fmin.html) and taking the comparison +/-0.0 < +/-0.0 will fail. > > This means the constant folded results will be: > fmin(0.0, 0.0) = 0.0 > fmin(0.0, -0.0) = 0.0 > fmin(-0.0, 0.0) = -0.0 > fmin(-0.0, -0.0) = -0.0 > > Other options would be to always use +0.0, or to be sensitive to the sign and claim -0.0 is less than 0.0. > > <0001-Add-fmin-fmax-intrinsics.patch> > <0002-Add-basic-fmin-fmax-instcombines.patch> > <0003-Fold-fmin-fmax-with-infinities.patch> > <0004-Move-fmin-fmax-constant-folding-logic-into-APFloat.patch>
… actually, now that I’m able double-check this, I’m quite surprised to find that we didn’t define fmax(+0,–0) in IEEE–754, which says [paraphrased]: minNum(x,y) is x if x < y, y if y < x, and the number if one is a number and the other is NaN. Otherwise, it is either x or y (this means results might differ among implementations). So I think your proposed semantics are perfectly reasonable. – Steve> On Aug 14, 2014, at 10:55 AM, Steve Canon <scanon at apple.com> wrote: > > I have no position on whether or not these should be added, but if they are they should match the IEEE 754 semantics, which fully specify all of these details. > > (Signaling NaNs could still be left unspecified as they're optional in IEEE-754). > > - Steve > > Sent from my iPhone > >> On Aug 13, 2014, at 7:38 PM, Matt Arsenault <arsenm2 at gmail.com> wrote: >> >> Hi, >> >> I’d like to re-propose adding intrinsics for fmin / fmax. These can be used to implement the equivalent libm functions as defined in C99 and OpenCL, which R600 and AArch64 at least have instructions with the same semantics. This is not equivalent to a simple fcmp + select due to its handling of NaNs. >> >> This has been proposed before, but never delivered (http://lists.cs.uiuc.edu/pipermail/llvmdev/2012-December/057128.html) >> >> To summarize: >> 1. If either operand is a NaN, returns the other operand >> 2. If both operands are NaN, returns NaN >> 3. If the operands are equal, returns a value that will compare equal to both arguments >> 4. In the normal case, returns the smaller / larger operand >> 5. Ignore what to do for signaling NaNs, since that’s what the rest of LLVM does currently anyway >> >> - Handling of fmin/fmax (+/- 0.0, +/- 0.0) >> Point 3 is worded as such because this doesn’t seem particularly well specified by any standard I’ve looked at. The most explicit mention of this I’ve found is a footnote in C99 that “Ideally, fmax would be sensitive to the sign of zero, for example fmax(-0.0, 0.0) would return +0; however, implementation in software might be impractical.” It doesn’t really state what the expected behavior is. glibc and OS X’s libc disagree on the (+0, -0) and (-0, +0) cases. To resolve this, the semantics of the intrinsic will be that either will be OK as long as the result compares equal. >> >> For the purposes of constant folding, I’ve tried to follow the literal wording which was most explicit for the expected result from OpenCL (http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/fmin.html) and taking the comparison +/-0.0 < +/-0.0 will fail. >> >> This means the constant folded results will be: >> fmin(0.0, 0.0) = 0.0 >> fmin(0.0, -0.0) = 0.0 >> fmin(-0.0, 0.0) = -0.0 >> fmin(-0.0, -0.0) = -0.0 >> >> Other options would be to always use +0.0, or to be sensitive to the sign and claim -0.0 is less than 0.0. >> >> <0001-Add-fmin-fmax-intrinsics.patch> >> <0002-Add-basic-fmin-fmax-instcombines.patch> >> <0003-Fold-fmin-fmax-with-infinities.patch> >> <0004-Move-fmin-fmax-constant-folding-logic-into-APFloat.patch>-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20140814/6dbbdfef/attachment.html>
FWIW, I am in favor of this proposal. —Owen On Aug 13, 2014, at 4:38 PM, Matt Arsenault <arsenm2 at gmail.com> wrote:> Hi, > > I’d like to re-propose adding intrinsics for fmin / fmax. These can be used to implement the equivalent libm functions as defined in C99 and OpenCL, which R600 and AArch64 at least have instructions with the same semantics. This is not equivalent to a simple fcmp + select due to its handling of NaNs. > > This has been proposed before, but never delivered (http://lists.cs.uiuc.edu/pipermail/llvmdev/2012-December/057128.html) > > To summarize: > 1. If either operand is a NaN, returns the other operand > 2. If both operands are NaN, returns NaN > 3. If the operands are equal, returns a value that will compare equal to both arguments > 4. In the normal case, returns the smaller / larger operand > 5. Ignore what to do for signaling NaNs, since that’s what the rest of LLVM does currently anyway > > - Handling of fmin/fmax (+/- 0.0, +/- 0.0) > Point 3 is worded as such because this doesn’t seem particularly well specified by any standard I’ve looked at. The most explicit mention of this I’ve found is a footnote in C99 that “Ideally, fmax would be sensitive to the sign of zero, for example fmax(-0.0, 0.0) would return +0; however, implementation in software might be impractical.” It doesn’t really state what the expected behavior is. glibc and OS X’s libc disagree on the (+0, -0) and (-0, +0) cases. To resolve this, the semantics of the intrinsic will be that either will be OK as long as the result compares equal. > > For the purposes of constant folding, I’ve tried to follow the literal wording which was most explicit for the expected result from OpenCL (http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/fmin.html) and taking the comparison +/-0.0 < +/-0.0 will fail. > > This means the constant folded results will be: > fmin(0.0, 0.0) = 0.0 > fmin(0.0, -0.0) = 0.0 > fmin(-0.0, 0.0) = -0.0 > fmin(-0.0, -0.0) = -0.0 > > Other options would be to always use +0.0, or to be sensitive to the sign and claim -0.0 is less than 0.0. > > <0001-Add-fmin-fmax-intrinsics.patch><0002-Add-basic-fmin-fmax-instcombines.patch><0003-Fold-fmin-fmax-with-infinities.patch><0004-Move-fmin-fmax-constant-folding-logic-into-APFloat.patch>
On Aug 13, 2014, at 7:38 PM, Matt Arsenault <arsenm2 at gmail.com> wrote:> Hi, > > I’d like to re-propose adding intrinsics for fmin / fmax. These can be used to implement the equivalent libm functions as defined in C99 and OpenCL, which R600 and AArch64 at least have instructions with the same semantics. This is not equivalent to a simple fcmp + select due to its handling of NaNs. > > This has been proposed before, but never delivered (http://lists.cs.uiuc.edu/pipermail/llvmdev/2012-December/057128.html) > > To summarize: > 1. If either operand is a NaN, returns the other operand > 2. If both operands are NaN, returns NaN > 3. If the operands are equal, returns a value that will compare equal to both arguments > 4. In the normal case, returns the smaller / larger operand > 5. Ignore what to do for signaling NaNs, since that’s what the rest of LLVM does currently anyway > > - Handling of fmin/fmax (+/- 0.0, +/- 0.0) > Point 3 is worded as such because this doesn’t seem particularly well specified by any standard I’ve looked at. The most explicit mention of this I’ve found is a footnote in C99 that “Ideally, fmax would be sensitive to the sign of zero, for example fmax(-0.0, 0.0) would return +0; however, implementation in software might be impractical.” It doesn’t really state what the expected behavior is. glibc and OS X’s libc disagree on the (+0, -0) and (-0, +0) cases. To resolve this, the semantics of the intrinsic will be that either will be OK as long as the result compares equal. > > For the purposes of constant folding, I’ve tried to follow the literal wording which was most explicit for the expected result from OpenCL (http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/fmin.html) and taking the comparison +/-0.0 < +/-0.0 will fail. > > This means the constant folded results will be: > fmin(0.0, 0.0) = 0.0 > fmin(0.0, -0.0) = 0.0 > fmin(-0.0, 0.0) = -0.0 > fmin(-0.0, -0.0) = -0.0 > > Other options would be to always use +0.0, or to be sensitive to the sign and claim -0.0 is less than 0.0. > > <0001-Add-fmin-fmax-intrinsics.patch><0002-Add-basic-fmin-fmax-instcombines.patch><0003-Fold-fmin-fmax-with-infinities.patch><0004-Move-fmin-fmax-constant-folding-logic-into-APFloat.patch>Post-vaction ping People seem to generally be in favor of adding these. Any comments on the specific patches adding them? -Matt
On Sep 3, 2014, at 9:14 AM, Matt Arsenault <arsenm2 at gmail.com> wrote:> > On Aug 13, 2014, at 7:38 PM, Matt Arsenault <arsenm2 at gmail.com> wrote: > >> Hi, >> >> I’d like to re-propose adding intrinsics for fmin / fmax. These can be used to implement the equivalent libm functions as defined in C99 and OpenCL, which R600 and AArch64 at least have instructions with the same semantics. This is not equivalent to a simple fcmp + select due to its handling of NaNs. >> >> This has been proposed before, but never delivered (http://lists.cs.uiuc.edu/pipermail/llvmdev/2012-December/057128.html) >> >> To summarize: >> 1. If either operand is a NaN, returns the other operand >> 2. If both operands are NaN, returns NaN >> 3. If the operands are equal, returns a value that will compare equal to both arguments >> 4. In the normal case, returns the smaller / larger operand >> 5. Ignore what to do for signaling NaNs, since that’s what the rest of LLVM does currently anyway >> >> - Handling of fmin/fmax (+/- 0.0, +/- 0.0) >> Point 3 is worded as such because this doesn’t seem particularly well specified by any standard I’ve looked at. The most explicit mention of this I’ve found is a footnote in C99 that “Ideally, fmax would be sensitive to the sign of zero, for example fmax(-0.0, 0.0) would return +0; however, implementation in software might be impractical.” It doesn’t really state what the expected behavior is. glibc and OS X’s libc disagree on the (+0, -0) and (-0, +0) cases. To resolve this, the semantics of the intrinsic will be that either will be OK as long as the result compares equal. >> >> For the purposes of constant folding, I’ve tried to follow the literal wording which was most explicit for the expected result from OpenCL (http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/fmin.html) and taking the comparison +/-0.0 < +/-0.0 will fail. >> >> This means the constant folded results will be: >> fmin(0.0, 0.0) = 0.0 >> fmin(0.0, -0.0) = 0.0 >> fmin(-0.0, 0.0) = -0.0 >> fmin(-0.0, -0.0) = -0.0 >> >> Other options would be to always use +0.0, or to be sensitive to the sign and claim -0.0 is less than 0.0. >> >> <0001-Add-fmin-fmax-intrinsics.patch><0002-Add-basic-fmin-fmax-instcombines.patch><0003-Fold-fmin-fmax-with-infinities.patch><0004-Move-fmin-fmax-constant-folding-logic-into-APFloat.patch> > > > Post-vaction ping > > People seem to generally be in favor of adding these. Any comments on the specific patches adding them?I have no specific comments other than to re-iterate my support for getting this in. —Owen
Apparently Analagous Threads
- [LLVMdev] [PATCH][RFC]: Add fmin/fmax intrinsics
- [LLVMdev] [PATCH][RFC]: Add fmin/fmax intrinsics
- [LLVMdev] [PATCH][RFC]: Add fmin/fmax intrinsics
- [LLVMdev] [PATCH][RFC]: Add fmin/fmax intrinsics
- RFC: What is the real behavior for the minnum/maxnum intrinsics?