Robison, Arch
2015-Jul-06 21:13 UTC
[LLVMdev] Why can't comparisons with negative zero be simplified?
In InstCombineCompares.cpp, routine InstCombiner::FoldFCmp_IntToFP_Cst, there
are these lines:
// Comparisons with zero are a special case where we know we won't lose
// information.
bool IsCmpZero = RHS.isPosZero();
// If the conversion would lose info, don't hack on this.
if ((int)InputSize > MantissaWidth && !IsCmpZero)
return nullptr;
Why check for positive zero instead of checking for any kind of zero? My
reading of IEEE 754-2008 is that floating-point comparison operations cannot
distinguish a negative zero from a positive zero. Further supporting this is
that fact that http://llvm.org/docs/LangRef.html describes the difference
between "ordered" and "unordered" as pertaining to QNAN
operands,
with no mention of negative zero.
I tried fixing the issue, but then the following test in cast-int-fcmp-eq-0.ll
fails:
; CHECK-LABEL: @i32_cast_cmp_oeq_int_n0_uitofp(
; CHECK: uitofp
; CHECK: fcmp oeq
define i1 @i32_cast_cmp_oeq_int_n0_uitofp(i32 %i) {
%f = uitofp i32 %i to float
%cmp = fcmp oeq float %f, -0.0
ret i1 %cmp
}
Is this test really justified, or is it just reinforcing an oversight?
- Arch D. Robison
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
<http://lists.llvm.org/pipermail/llvm-dev/attachments/20150706/d575d72e/attachment.html>
Sean Silva
2015-Jul-06 22:06 UTC
[LLVMdev] Why can't comparisons with negative zero be simplified?
+Matt who is the one that originally committed this (r225265). -- Sean Silva On Mon, Jul 6, 2015 at 2:13 PM, Robison, Arch <arch.robison at intel.com> wrote:> In InstCombineCompares.cpp, routine InstCombiner::FoldFCmp_IntToFP_Cst, > there are these lines: > > > > // Comparisons with zero are a special case where we know we won't lose > > // information. > > bool IsCmpZero = RHS.isPosZero(); > > > > // If the conversion would lose info, don't hack on this. > > if ((int)InputSize > MantissaWidth && !IsCmpZero) > > return nullptr; > > > > Why check for positive zero instead of checking for any kind of zero? My > reading of IEEE 754-2008 is that floating-point comparison operations > cannot distinguish a negative zero from a positive zero. Further > supporting this is that fact that http://llvm.org/docs/LangRef.html > <https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_docs_LangRef.html&d=AwMFAg&c=8hUWFZcy2Z-Za5rBPlktOQ&r=Mfk2qtn1LTDThVkh6-oGglNfMADXfJdty4_bhmuhMHA&m=ZaWNNVon_US-YjLoXztqD5ve4xvIIhIXYdnk3Xqwz8w&s=xonYObEo1TXUyjK3RYC4Pg3kAaSvaYy_Lnvaiq5G1N0&e=> > describes the difference between “ordered” and “unordered” as pertaining to > QNAN operands, > > with no mention of negative zero. > > > > I tried fixing the issue, but then the following test in > cast-int-fcmp-eq-0.ll fails: > > > > ; CHECK-LABEL: @i32_cast_cmp_oeq_int_n0_uitofp( > > ; CHECK: uitofp > > ; CHECK: fcmp oeq > > define i1 @i32_cast_cmp_oeq_int_n0_uitofp(i32 %i) { > > %f = uitofp i32 %i to float > > %cmp = fcmp oeq float %f, -0.0 > > ret i1 %cmp > > } > > > > Is this test really justified, or is it just reinforcing an oversight? > > > > - Arch D. Robison > > _______________________________________________ > LLVM Developers mailing list > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev > >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20150706/9b0c6074/attachment.html>
Sean Silva
2015-Jul-06 22:22 UTC
[LLVMdev] Why can't comparisons with negative zero be simplified?
It seems like -0 should be fine. -- Sean Silva On Mon, Jul 6, 2015 at 2:13 PM, Robison, Arch <arch.robison at intel.com> wrote:> In InstCombineCompares.cpp, routine InstCombiner::FoldFCmp_IntToFP_Cst, > there are these lines: > > > > // Comparisons with zero are a special case where we know we won't lose > > // information. > > bool IsCmpZero = RHS.isPosZero(); > > > > // If the conversion would lose info, don't hack on this. > > if ((int)InputSize > MantissaWidth && !IsCmpZero) > > return nullptr; > > > > Why check for positive zero instead of checking for any kind of zero? My > reading of IEEE 754-2008 is that floating-point comparison operations > cannot distinguish a negative zero from a positive zero. Further > supporting this is that fact that http://llvm.org/docs/LangRef.html > <https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_docs_LangRef.html&d=AwMFAg&c=8hUWFZcy2Z-Za5rBPlktOQ&r=Mfk2qtn1LTDThVkh6-oGglNfMADXfJdty4_bhmuhMHA&m=ZaWNNVon_US-YjLoXztqD5ve4xvIIhIXYdnk3Xqwz8w&s=xonYObEo1TXUyjK3RYC4Pg3kAaSvaYy_Lnvaiq5G1N0&e=> > describes the difference between “ordered” and “unordered” as pertaining to > QNAN operands, > > with no mention of negative zero. > > > > I tried fixing the issue, but then the following test in > cast-int-fcmp-eq-0.ll fails: > > > > ; CHECK-LABEL: @i32_cast_cmp_oeq_int_n0_uitofp( > > ; CHECK: uitofp > > ; CHECK: fcmp oeq > > define i1 @i32_cast_cmp_oeq_int_n0_uitofp(i32 %i) { > > %f = uitofp i32 %i to float > > %cmp = fcmp oeq float %f, -0.0 > > ret i1 %cmp > > } > > > > Is this test really justified, or is it just reinforcing an oversight? > > > > - Arch D. Robison > > _______________________________________________ > LLVM Developers mailing list > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev > >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20150706/0aa7c74c/attachment.html>
Matt Arsenault
2015-Jul-06 22:48 UTC
[LLVMdev] Why can't comparisons with negative zero be simplified?
On 07/06/2015 03:06 PM, Sean Silva wrote:> +Matt who is the one that originally committed this (r225265). > > -- Sean SilvaI think it's fine, but I was being extremely conservative with what it allows. This really should work in a lot more cases. Before my patch, it only worked for smaller integer types instead of considering the values. When I was working on this, I had it checking if the constant being compared could be represented by the integer type (e.g. fcmp eq with a fractional value -> false and also allow the non-equality compares). I think it was just disturbingly hard to break and I was afraid of breaking some edge case when the only real world cases I really cared about was eq/ne 0. -Matt
Sean Silva
2015-Jul-06 23:09 UTC
[LLVMdev] Why can't comparisons with negative zero be simplified?
The way FoldFCmp_IntToFP_Cst works is confusing to me. What it is trying to
do basically boils down to taking the set of real numbers where fcmp(?,
Cst) is true, then finding the inverse image under the mapping [us]itofp of
that set (i.e. all the integers (of the relevant type) that can map to
values in that set under the operation [us]itofp). That inverse image is
guaranteed to be contiguous, so at most two integer comparisons suffice. If
the inverse image is just a single value, then a single equality comparison
suffices. If the inverse image includes the {maximal,minimal}
{signed,unsigned} integer, then a single integer order comparison suffices.
So e.g. consider
fcmp oeq double (uitofp x) Cst
With Cst = 2^62 + ulp(2^62)), i.e. 2^62*(0b1.0000....1), where the final 1
is in the least significant bit.
Then the set of real numbers for which `fcmp oeq double
roundToFloat(realNumber) Cst` yields true is the open interval (a,b) where
a = 2^62 + .5*ulp(2^62)
b = 2^62 + 1.5*ulp(2^62)
i.e. the open interval bracketed by Cst +/- .5*ulp(Cst)
(assuming round to nearest ties to even rounding mode)
However, since ulp(Cst) = ulp(2^62) = 2^62 * 2^-52 = 2^10, this means that
this range covers
(2^62 + (1/2)*2^10, 2^62 + (3/2)*2^10) = [2^62 + (1/2)*2^10 + 1, 2^62 +
(3/2)*2^10 - 1] which contains 1022 integers, so a range comparison is
needed.
(note: for Cst = 2^62, the interval is only half as large on the low side
since Cst lies on the boundary where the exponent changes, i.e. the
interval is [Cst - .25*ulp(Cst), Cst + .5*ulp(Cst)]; the closed interval is
due to 2^62 being even)
This of course requires baking in a rounding mode, but we are already doing
that anyway.
-- Sean Silva
On Mon, Jul 6, 2015 at 2:13 PM, Robison, Arch <arch.robison at intel.com>
wrote:
> In InstCombineCompares.cpp, routine InstCombiner::FoldFCmp_IntToFP_Cst,
> there are these lines:
>
>
>
> // Comparisons with zero are a special case where we know we won't
lose
>
> // information.
>
> bool IsCmpZero = RHS.isPosZero();
>
>
>
> // If the conversion would lose info, don't hack on this.
>
> if ((int)InputSize > MantissaWidth && !IsCmpZero)
>
> return nullptr;
>
>
>
> Why check for positive zero instead of checking for any kind of zero? My
> reading of IEEE 754-2008 is that floating-point comparison operations
> cannot distinguish a negative zero from a positive zero. Further
> supporting this is that fact that http://llvm.org/docs/LangRef.html
>
<https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_docs_LangRef.html&d=AwMFAg&c=8hUWFZcy2Z-Za5rBPlktOQ&r=Mfk2qtn1LTDThVkh6-oGglNfMADXfJdty4_bhmuhMHA&m=ZaWNNVon_US-YjLoXztqD5ve4xvIIhIXYdnk3Xqwz8w&s=xonYObEo1TXUyjK3RYC4Pg3kAaSvaYy_Lnvaiq5G1N0&e=>
> describes the difference between “ordered” and “unordered” as pertaining to
> QNAN operands,
>
> with no mention of negative zero.
>
>
>
> I tried fixing the issue, but then the following test in
> cast-int-fcmp-eq-0.ll fails:
>
>
>
> ; CHECK-LABEL: @i32_cast_cmp_oeq_int_n0_uitofp(
>
> ; CHECK: uitofp
>
> ; CHECK: fcmp oeq
>
> define i1 @i32_cast_cmp_oeq_int_n0_uitofp(i32 %i) {
>
> %f = uitofp i32 %i to float
>
> %cmp = fcmp oeq float %f, -0.0
>
> ret i1 %cmp
>
> }
>
>
>
> Is this test really justified, or is it just reinforcing an oversight?
>
>
>
> - Arch D. Robison
>
> _______________________________________________
> LLVM Developers mailing list
> LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
<http://lists.llvm.org/pipermail/llvm-dev/attachments/20150706/292ecc0c/attachment.html>
Robison, Arch
2015-Jul-07 14:33 UTC
[LLVMdev] Why can't comparisons with negative zero be simplified?
I concur with your analysis.
I was planning to just extend the applicability of the current transform by just
taking on more cases where the inverse image is a single value. Though if
someone else wants to take on the general range case, I’m happy to step aside.
:-)
- Arch
From: Sean Silva [mailto:chisophugis at gmail.com]
Sent: Monday, July 6, 2015 6:10 PM
To: Robison, Arch
Cc: llvmdev at cs.uiuc.edu
Subject: Re: [LLVMdev] Why can't comparisons with negative zero be
simplified?
The way FoldFCmp_IntToFP_Cst works is confusing to me. What it is trying to do
basically boils down to taking the set of real numbers where fcmp(?, Cst) is
true, then finding the inverse image under the mapping [us]itofp of that set
(i.e. all the integers (of the relevant type) that can map to values in that set
under the operation [us]itofp). That inverse image is guaranteed to be
contiguous, so at most two integer comparisons suffice. If the inverse image is
just a single value, then a single equality comparison suffices. If the inverse
image includes the {maximal,minimal} {signed,unsigned} integer, then a single
integer order comparison suffices.
So e.g. consider
fcmp oeq double (uitofp x) Cst
With Cst = 2^62 + ulp(2^62)), i.e. 2^62*(0b1.0000....1), where the final 1 is in
the least significant bit.
Then the set of real numbers for which `fcmp oeq double roundToFloat(realNumber)
Cst` yields true is the open interval (a,b) where
a = 2^62 + .5*ulp(2^62)
b = 2^62 + 1.5*ulp(2^62)
i.e. the open interval bracketed by Cst +/- .5*ulp(Cst)
(assuming round to nearest ties to even rounding mode)
However, since ulp(Cst) = ulp(2^62) = 2^62 * 2^-52 = 2^10, this means that this
range covers
(2^62 + (1/2)*2^10, 2^62 + (3/2)*2^10) = [2^62 + (1/2)*2^10 + 1, 2^62 +
(3/2)*2^10 - 1] which contains 1022 integers, so a range comparison is needed.
(note: for Cst = 2^62, the interval is only half as large on the low side since
Cst lies on the boundary where the exponent changes, i.e. the interval is [Cst -
.25*ulp(Cst), Cst + .5*ulp(Cst)]; the closed interval is due to 2^62 being even)
This of course requires baking in a rounding mode, but we are already doing that
anyway.
-- Sean Silva
On Mon, Jul 6, 2015 at 2:13 PM, Robison, Arch <arch.robison at
intel.com<mailto:arch.robison at intel.com>> wrote:
In InstCombineCompares.cpp, routine InstCombiner::FoldFCmp_IntToFP_Cst, there
are these lines:
// Comparisons with zero are a special case where we know we won't lose
// information.
bool IsCmpZero = RHS.isPosZero();
// If the conversion would lose info, don't hack on this.
if ((int)InputSize > MantissaWidth && !IsCmpZero)
return nullptr;
Why check for positive zero instead of checking for any kind of zero? My
reading of IEEE 754-2008 is that floating-point comparison operations cannot
distinguish a negative zero from a positive zero. Further supporting this is
that fact that
http://llvm.org/docs/LangRef.html<https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_docs_LangRef.html&d=AwMFAg&c=8hUWFZcy2Z-Za5rBPlktOQ&r=Mfk2qtn1LTDThVkh6-oGglNfMADXfJdty4_bhmuhMHA&m=ZaWNNVon_US-YjLoXztqD5ve4xvIIhIXYdnk3Xqwz8w&s=xonYObEo1TXUyjK3RYC4Pg3kAaSvaYy_Lnvaiq5G1N0&e=>
describes the difference between “ordered” and “unordered” as pertaining to QNAN
operands,
with no mention of negative zero.
I tried fixing the issue, but then the following test in cast-int-fcmp-eq-0.ll
fails:
; CHECK-LABEL: @i32_cast_cmp_oeq_int_n0_uitofp(
; CHECK: uitofp
; CHECK: fcmp oeq
define i1 @i32_cast_cmp_oeq_int_n0_uitofp(i32 %i) {
%f = uitofp i32 %i to float
%cmp = fcmp oeq float %f, -0.0
ret i1 %cmp
}
Is this test really justified, or is it just reinforcing an oversight?
- Arch D. Robison
_______________________________________________
LLVM Developers mailing list
LLVMdev at cs.uiuc.edu<mailto:LLVMdev at cs.uiuc.edu>
http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
<http://lists.llvm.org/pipermail/llvm-dev/attachments/20150707/1857dd4c/attachment.html>